1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2*387f9dfdSAndroid Build Coastguard Worker // Copyright (c) 2020 Wenbo Zhang
3*387f9dfdSAndroid Build Coastguard Worker //
4*387f9dfdSAndroid Build Coastguard Worker // Based on numamove(8) from BPF-Perf-Tools-Book by Brendan Gregg.
5*387f9dfdSAndroid Build Coastguard Worker // 8-Jun-2020 Wenbo Zhang Created this.
6*387f9dfdSAndroid Build Coastguard Worker // 30-Jan-2023 Rong Tao Use fentry_can_attach() to decide use fentry/kprobe.
7*387f9dfdSAndroid Build Coastguard Worker #include <argp.h>
8*387f9dfdSAndroid Build Coastguard Worker #include <signal.h>
9*387f9dfdSAndroid Build Coastguard Worker #include <stdio.h>
10*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
11*387f9dfdSAndroid Build Coastguard Worker #include <time.h>
12*387f9dfdSAndroid Build Coastguard Worker #include <bpf/libbpf.h>
13*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf.h>
14*387f9dfdSAndroid Build Coastguard Worker #include "numamove.skel.h"
15*387f9dfdSAndroid Build Coastguard Worker #include "trace_helpers.h"
16*387f9dfdSAndroid Build Coastguard Worker
17*387f9dfdSAndroid Build Coastguard Worker static struct env {
18*387f9dfdSAndroid Build Coastguard Worker bool verbose;
19*387f9dfdSAndroid Build Coastguard Worker } env;
20*387f9dfdSAndroid Build Coastguard Worker
21*387f9dfdSAndroid Build Coastguard Worker static volatile bool exiting;
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard Worker const char *argp_program_version = "numamove 0.1";
24*387f9dfdSAndroid Build Coastguard Worker const char *argp_program_bug_address =
25*387f9dfdSAndroid Build Coastguard Worker "https://github.com/iovisor/bcc/tree/master/libbpf-tools";
26*387f9dfdSAndroid Build Coastguard Worker const char argp_program_doc[] =
27*387f9dfdSAndroid Build Coastguard Worker "Show page migrations of type NUMA misplaced per second.\n"
28*387f9dfdSAndroid Build Coastguard Worker "\n"
29*387f9dfdSAndroid Build Coastguard Worker "USAGE: numamove [--help]\n"
30*387f9dfdSAndroid Build Coastguard Worker "\n"
31*387f9dfdSAndroid Build Coastguard Worker "EXAMPLES:\n"
32*387f9dfdSAndroid Build Coastguard Worker " numamove # Show page migrations' count and latency";
33*387f9dfdSAndroid Build Coastguard Worker
34*387f9dfdSAndroid Build Coastguard Worker static const struct argp_option opts[] = {
35*387f9dfdSAndroid Build Coastguard Worker { "verbose", 'v', NULL, 0, "Verbose debug output" },
36*387f9dfdSAndroid Build Coastguard Worker { NULL, 'h', NULL, OPTION_HIDDEN, "Show the full help" },
37*387f9dfdSAndroid Build Coastguard Worker {},
38*387f9dfdSAndroid Build Coastguard Worker };
39*387f9dfdSAndroid Build Coastguard Worker
parse_arg(int key,char * arg,struct argp_state * state)40*387f9dfdSAndroid Build Coastguard Worker static error_t parse_arg(int key, char *arg, struct argp_state *state)
41*387f9dfdSAndroid Build Coastguard Worker {
42*387f9dfdSAndroid Build Coastguard Worker switch (key) {
43*387f9dfdSAndroid Build Coastguard Worker case 'h':
44*387f9dfdSAndroid Build Coastguard Worker argp_state_help(state, stderr, ARGP_HELP_STD_HELP);
45*387f9dfdSAndroid Build Coastguard Worker break;
46*387f9dfdSAndroid Build Coastguard Worker case 'v':
47*387f9dfdSAndroid Build Coastguard Worker env.verbose = true;
48*387f9dfdSAndroid Build Coastguard Worker break;
49*387f9dfdSAndroid Build Coastguard Worker default:
50*387f9dfdSAndroid Build Coastguard Worker return ARGP_ERR_UNKNOWN;
51*387f9dfdSAndroid Build Coastguard Worker }
52*387f9dfdSAndroid Build Coastguard Worker return 0;
53*387f9dfdSAndroid Build Coastguard Worker }
54*387f9dfdSAndroid Build Coastguard Worker
libbpf_print_fn(enum libbpf_print_level level,const char * format,va_list args)55*387f9dfdSAndroid Build Coastguard Worker static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
56*387f9dfdSAndroid Build Coastguard Worker {
57*387f9dfdSAndroid Build Coastguard Worker if (level == LIBBPF_DEBUG && !env.verbose)
58*387f9dfdSAndroid Build Coastguard Worker return 0;
59*387f9dfdSAndroid Build Coastguard Worker return vfprintf(stderr, format, args);
60*387f9dfdSAndroid Build Coastguard Worker }
61*387f9dfdSAndroid Build Coastguard Worker
sig_handler(int sig)62*387f9dfdSAndroid Build Coastguard Worker static void sig_handler(int sig)
63*387f9dfdSAndroid Build Coastguard Worker {
64*387f9dfdSAndroid Build Coastguard Worker exiting = true;
65*387f9dfdSAndroid Build Coastguard Worker }
66*387f9dfdSAndroid Build Coastguard Worker
main(int argc,char ** argv)67*387f9dfdSAndroid Build Coastguard Worker int main(int argc, char **argv)
68*387f9dfdSAndroid Build Coastguard Worker {
69*387f9dfdSAndroid Build Coastguard Worker static const struct argp argp = {
70*387f9dfdSAndroid Build Coastguard Worker .options = opts,
71*387f9dfdSAndroid Build Coastguard Worker .parser = parse_arg,
72*387f9dfdSAndroid Build Coastguard Worker .doc = argp_program_doc,
73*387f9dfdSAndroid Build Coastguard Worker };
74*387f9dfdSAndroid Build Coastguard Worker struct numamove_bpf *obj;
75*387f9dfdSAndroid Build Coastguard Worker struct tm *tm;
76*387f9dfdSAndroid Build Coastguard Worker char ts[32];
77*387f9dfdSAndroid Build Coastguard Worker time_t t;
78*387f9dfdSAndroid Build Coastguard Worker int err;
79*387f9dfdSAndroid Build Coastguard Worker
80*387f9dfdSAndroid Build Coastguard Worker err = argp_parse(&argp, argc, argv, 0, NULL, NULL);
81*387f9dfdSAndroid Build Coastguard Worker if (err)
82*387f9dfdSAndroid Build Coastguard Worker return err;
83*387f9dfdSAndroid Build Coastguard Worker
84*387f9dfdSAndroid Build Coastguard Worker libbpf_set_print(libbpf_print_fn);
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Worker obj = numamove_bpf__open();
87*387f9dfdSAndroid Build Coastguard Worker if (!obj) {
88*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to open and/or load BPF object\n");
89*387f9dfdSAndroid Build Coastguard Worker return 1;
90*387f9dfdSAndroid Build Coastguard Worker }
91*387f9dfdSAndroid Build Coastguard Worker
92*387f9dfdSAndroid Build Coastguard Worker if (!obj->bss) {
93*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "Memory-mapping BPF maps is supported starting from Linux 5.7, please upgrade.\n");
94*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
95*387f9dfdSAndroid Build Coastguard Worker }
96*387f9dfdSAndroid Build Coastguard Worker
97*387f9dfdSAndroid Build Coastguard Worker /* It fallbacks to kprobes when kernel does not support fentry. */
98*387f9dfdSAndroid Build Coastguard Worker if (fentry_can_attach("migrate_misplaced_page", NULL)) {
99*387f9dfdSAndroid Build Coastguard Worker bpf_program__set_autoload(obj->progs.kprobe_migrate_misplaced_page, false);
100*387f9dfdSAndroid Build Coastguard Worker bpf_program__set_autoload(obj->progs.kretprobe_migrate_misplaced_page_exit, false);
101*387f9dfdSAndroid Build Coastguard Worker } else {
102*387f9dfdSAndroid Build Coastguard Worker bpf_program__set_autoload(obj->progs.fentry_migrate_misplaced_page, false);
103*387f9dfdSAndroid Build Coastguard Worker bpf_program__set_autoload(obj->progs.fexit_migrate_misplaced_page_exit, false);
104*387f9dfdSAndroid Build Coastguard Worker }
105*387f9dfdSAndroid Build Coastguard Worker
106*387f9dfdSAndroid Build Coastguard Worker err = numamove_bpf__load(obj);
107*387f9dfdSAndroid Build Coastguard Worker if (err) {
108*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to load BPF skelect: %d\n", err);
109*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
110*387f9dfdSAndroid Build Coastguard Worker }
111*387f9dfdSAndroid Build Coastguard Worker
112*387f9dfdSAndroid Build Coastguard Worker err = numamove_bpf__attach(obj);
113*387f9dfdSAndroid Build Coastguard Worker if (err) {
114*387f9dfdSAndroid Build Coastguard Worker fprintf(stderr, "failed to attach BPF programs\n");
115*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
116*387f9dfdSAndroid Build Coastguard Worker }
117*387f9dfdSAndroid Build Coastguard Worker
118*387f9dfdSAndroid Build Coastguard Worker signal(SIGINT, sig_handler);
119*387f9dfdSAndroid Build Coastguard Worker
120*387f9dfdSAndroid Build Coastguard Worker printf("%-10s %18s %18s\n", "TIME", "NUMA_migrations", "NUMA_migrations_ms");
121*387f9dfdSAndroid Build Coastguard Worker while (!exiting) {
122*387f9dfdSAndroid Build Coastguard Worker sleep(1);
123*387f9dfdSAndroid Build Coastguard Worker time(&t);
124*387f9dfdSAndroid Build Coastguard Worker tm = localtime(&t);
125*387f9dfdSAndroid Build Coastguard Worker strftime(ts, sizeof(ts), "%H:%M:%S", tm);
126*387f9dfdSAndroid Build Coastguard Worker printf("%-10s %18lld %18lld\n", ts,
127*387f9dfdSAndroid Build Coastguard Worker __atomic_exchange_n(&obj->bss->num, 0, __ATOMIC_RELAXED),
128*387f9dfdSAndroid Build Coastguard Worker __atomic_exchange_n(&obj->bss->latency, 0, __ATOMIC_RELAXED));
129*387f9dfdSAndroid Build Coastguard Worker }
130*387f9dfdSAndroid Build Coastguard Worker
131*387f9dfdSAndroid Build Coastguard Worker cleanup:
132*387f9dfdSAndroid Build Coastguard Worker numamove_bpf__destroy(obj);
133*387f9dfdSAndroid Build Coastguard Worker return err != 0;
134*387f9dfdSAndroid Build Coastguard Worker }
135