cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

libperf-counting.txt (5607B)


      1libperf-counting(7)
      2===================
      3
      4NAME
      5----
      6libperf-counting - counting interface
      7
      8DESCRIPTION
      9-----------
     10The counting interface provides API to measure and get count for specific perf events.
     11
     12The following test tries to explain count on `counting.c` example.
     13
     14It is by no means complete guide to counting, but shows libperf basic API for counting.
     15
     16The `counting.c` comes with libperf package and can be compiled and run like:
     17
     18[source,bash]
     19--
     20$ gcc -o counting counting.c -lperf
     21$ sudo ./counting
     22count 176792, enabled 176944, run 176944
     23count 176242, enabled 176242, run 176242
     24--
     25
     26It requires root access, because of the `PERF_COUNT_SW_CPU_CLOCK` event,
     27which is available only for root.
     28
     29The `counting.c` example monitors two events on the current process and displays
     30their count, in a nutshell it:
     31
     32* creates events
     33* adds them to the event list
     34* opens and enables events through the event list
     35* does some workload
     36* disables events
     37* reads and displays event counts
     38* destroys the event list
     39
     40The first thing you need to do before using libperf is to call init function:
     41
     42[source,c]
     43--
     44  8 static int libperf_print(enum libperf_print_level level,
     45  9                          const char *fmt, va_list ap)
     46 10 {
     47 11         return vfprintf(stderr, fmt, ap);
     48 12 }
     49
     50 14 int main(int argc, char **argv)
     51 15 {
     52 ...
     53 35         libperf_init(libperf_print);
     54--
     55
     56It will setup the library and sets function for debug output from library.
     57
     58The `libperf_print` callback will receive any message with its debug level,
     59defined as:
     60
     61[source,c]
     62--
     63enum libperf_print_level {
     64        LIBPERF_ERR,
     65        LIBPERF_WARN,
     66        LIBPERF_INFO,
     67        LIBPERF_DEBUG,
     68        LIBPERF_DEBUG2,
     69        LIBPERF_DEBUG3,
     70};
     71--
     72
     73Once the setup is complete we start by defining specific events using the `struct perf_event_attr`.
     74
     75We create software events for cpu and task:
     76
     77[source,c]
     78--
     79 20         struct perf_event_attr attr1 = {
     80 21                 .type        = PERF_TYPE_SOFTWARE,
     81 22                 .config      = PERF_COUNT_SW_CPU_CLOCK,
     82 23                 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING,
     83 24                 .disabled    = 1,
     84 25         };
     85 26         struct perf_event_attr attr2 = {
     86 27                 .type        = PERF_TYPE_SOFTWARE,
     87 28                 .config      = PERF_COUNT_SW_TASK_CLOCK,
     88 29                 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING,
     89 30                 .disabled    = 1,
     90 31         };
     91--
     92
     93The `read_format` setup tells perf to include timing details together with each count.
     94
     95Next step is to prepare threads map.
     96
     97In this case we will monitor current process, so we create threads map with single pid (0):
     98
     99[source,c]
    100--
    101 37         threads = perf_thread_map__new_dummy();
    102 38         if (!threads) {
    103 39                 fprintf(stderr, "failed to create threads\n");
    104 40                 return -1;
    105 41         }
    106 42
    107 43         perf_thread_map__set_pid(threads, 0, 0);
    108--
    109
    110Now we create libperf's event list, which will serve as holder for the events we want:
    111
    112[source,c]
    113--
    114 45         evlist = perf_evlist__new();
    115 46         if (!evlist) {
    116 47                 fprintf(stderr, "failed to create evlist\n");
    117 48                 goto out_threads;
    118 49         }
    119--
    120
    121We create libperf's events for the attributes we defined earlier and add them to the list:
    122
    123[source,c]
    124--
    125 51         evsel = perf_evsel__new(&attr1);
    126 52         if (!evsel) {
    127 53                 fprintf(stderr, "failed to create evsel1\n");
    128 54                 goto out_evlist;
    129 55         }
    130 56
    131 57         perf_evlist__add(evlist, evsel);
    132 58
    133 59         evsel = perf_evsel__new(&attr2);
    134 60         if (!evsel) {
    135 61                 fprintf(stderr, "failed to create evsel2\n");
    136 62                 goto out_evlist;
    137 63         }
    138 64
    139 65         perf_evlist__add(evlist, evsel);
    140--
    141
    142Configure event list with the thread map and open events:
    143
    144[source,c]
    145--
    146 67         perf_evlist__set_maps(evlist, NULL, threads);
    147 68
    148 69         err = perf_evlist__open(evlist);
    149 70         if (err) {
    150 71                 fprintf(stderr, "failed to open evsel\n");
    151 72                 goto out_evlist;
    152 73         }
    153--
    154
    155Both events are created as disabled (note the `disabled = 1` assignment above),
    156so we need to enable the whole list explicitly (both events).
    157
    158From this moment events are counting and we can do our workload.
    159
    160When we are done we disable the events list.
    161
    162[source,c]
    163--
    164 75         perf_evlist__enable(evlist);
    165 76
    166 77         while (count--);
    167 78
    168 79         perf_evlist__disable(evlist);
    169--
    170
    171Now we need to get the counts from events, following code iterates through the
    172events list and read counts:
    173
    174[source,c]
    175--
    176 81         perf_evlist__for_each_evsel(evlist, evsel) {
    177 82                 perf_evsel__read(evsel, 0, 0, &counts);
    178 83                 fprintf(stdout, "count %llu, enabled %llu, run %llu\n",
    179 84                         counts.val, counts.ena, counts.run);
    180 85         }
    181--
    182
    183And finally cleanup.
    184
    185We close the whole events list (both events) and remove it together with the threads map:
    186
    187[source,c]
    188--
    189 87         perf_evlist__close(evlist);
    190 88
    191 89 out_evlist:
    192 90         perf_evlist__delete(evlist);
    193 91 out_threads:
    194 92         perf_thread_map__put(threads);
    195 93         return err;
    196 94 }
    197--
    198
    199REPORTING BUGS
    200--------------
    201Report bugs to <linux-perf-users@vger.kernel.org>.
    202
    203LICENSE
    204-------
    205libperf is Free Software licensed under the GNU LGPL 2.1
    206
    207RESOURCES
    208---------
    209https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    210
    211SEE ALSO
    212--------
    213libperf(3), libperf-sampling(7)