OSDN Git Service

i386/xen: handle HVMOP_get_param
[qmiga/qemu.git] / scripts / userfaultfd-wrlat.py
1 #!/usr/bin/python3
2 #
3 # userfaultfd-wrlat Summarize userfaultfd write fault latencies.
4 #                   Events are continuously accumulated for the
5 #                   run, while latency distribution histogram is
6 #                   dumped each 'interval' seconds.
7 #
8 #                   For Linux, uses BCC, eBPF.
9 #
10 # USAGE: userfaultfd-lat [interval [count]]
11 #
12 # Copyright Virtuozzo GmbH, 2020
13 #
14 # Authors:
15 #   Andrey Gruzdev   <andrey.gruzdev@virtuozzo.com>
16 #
17 # This work is licensed under the terms of the GNU GPL, version 2 or
18 # later.  See the COPYING file in the top-level directory.
19
20 from __future__ import print_function
21 from bcc import BPF
22 from ctypes import c_ushort, c_int, c_ulonglong
23 from time import sleep
24 from sys import argv
25
26 def usage():
27     print("USAGE: %s [interval [count]]" % argv[0])
28     exit()
29
30 # define BPF program
31 bpf_text = """
32 #include <uapi/linux/ptrace.h>
33 #include <linux/mm.h>
34
35 BPF_HASH(ev_start, u32, u64);
36 BPF_HISTOGRAM(ev_delta_hist, u64);
37
38 /* Trace UFFD page fault start event. */
39 static void do_event_start()
40 {
41     /* Using "(u32)" to drop group ID which is upper 32 bits */
42     u32 tid = (u32) bpf_get_current_pid_tgid();
43     u64 ts = bpf_ktime_get_ns();
44
45     ev_start.update(&tid, &ts);
46 }
47
48 /* Trace UFFD page fault end event. */
49 static void do_event_end()
50 {
51     /* Using "(u32)" to drop group ID which is upper 32 bits */
52     u32 tid = (u32) bpf_get_current_pid_tgid();
53     u64 ts = bpf_ktime_get_ns();
54     u64 *tsp;
55
56     tsp = ev_start.lookup(&tid);
57     if (tsp) {
58         u64 delta = ts - (*tsp);
59         /* Transform time delta to milliseconds */
60         ev_delta_hist.increment(bpf_log2l(delta / 1000000));
61         ev_start.delete(&tid);
62     }
63 }
64
65 /* KPROBE for handle_userfault(). */
66 int probe_handle_userfault(struct pt_regs *ctx, struct vm_fault *vmf,
67         unsigned long reason)
68 {
69     /* Trace only UFFD write faults. */
70     if (reason & VM_UFFD_WP) {
71         do_event_start();
72     }
73     return 0;
74 }
75
76 /* KRETPROBE for handle_userfault(). */
77 int retprobe_handle_userfault(struct pt_regs *ctx)
78 {
79     do_event_end();
80     return 0;
81 }
82 """
83
84 # arguments
85 interval = 10
86 count = -1
87 if len(argv) > 1:
88     try:
89         interval = int(argv[1])
90         if interval == 0:
91             raise
92         if len(argv) > 2:
93             count = int(argv[2])
94     except:    # also catches -h, --help
95         usage()
96
97 # load BPF program
98 b = BPF(text=bpf_text)
99 # attach KRPOBEs
100 b.attach_kprobe(event="handle_userfault", fn_name="probe_handle_userfault")
101 b.attach_kretprobe(event="handle_userfault", fn_name="retprobe_handle_userfault")
102
103 # header
104 print("Tracing UFFD-WP write fault latency... Hit Ctrl-C to end.")
105
106 # output
107 loop = 0
108 do_exit = 0
109 while (1):
110     if count > 0:
111         loop += 1
112         if loop > count:
113             exit()
114     try:
115         sleep(interval)
116     except KeyboardInterrupt:
117         pass; do_exit = 1
118
119     print()
120     b["ev_delta_hist"].print_log2_hist("msecs")
121     if do_exit:
122         exit()