cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

userfaultfd-wrlat.py (2938B)


      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
     20from __future__ import print_function
     21from bcc import BPF
     22from ctypes import c_ushort, c_int, c_ulonglong
     23from time import sleep
     24from sys import argv
     25
     26def usage():
     27    print("USAGE: %s [interval [count]]" % argv[0])
     28    exit()
     29
     30# define BPF program
     31bpf_text = """
     32#include <uapi/linux/ptrace.h>
     33#include <linux/mm.h>
     34
     35BPF_HASH(ev_start, u32, u64);
     36BPF_HISTOGRAM(ev_delta_hist, u64);
     37
     38/* Trace UFFD page fault start event. */
     39static 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. */
     49static 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(). */
     66int 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(). */
     77int retprobe_handle_userfault(struct pt_regs *ctx)
     78{
     79    do_event_end();
     80    return 0;
     81}
     82"""
     83
     84# arguments
     85interval = 10
     86count = -1
     87if 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
     98b = BPF(text=bpf_text)
     99# attach KRPOBEs
    100b.attach_kprobe(event="handle_userfault", fn_name="probe_handle_userfault")
    101b.attach_kretprobe(event="handle_userfault", fn_name="retprobe_handle_userfault")
    102
    103# header
    104print("Tracing UFFD-WP write fault latency... Hit Ctrl-C to end.")
    105
    106# output
    107loop = 0
    108do_exit = 0
    109while (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()