Back to home page

OSCL-LXR

 
 

    


0001 #include <stdbool.h>
0002 #include <stdlib.h>
0003 #include <linux/kernel.h>
0004 #include <linux/types.h>
0005 #include <linux/bitops.h>
0006 #include <linux/log2.h>
0007 #include <linux/zalloc.h>
0008 
0009 #include "../../util/evlist.h"
0010 #include "../../util/auxtrace.h"
0011 #include "../../util/evsel.h"
0012 #include "../../util/record.h"
0013 
0014 #define PERF_EVENT_CPUM_SF      0xB0000 /* Event: Basic-sampling */
0015 #define PERF_EVENT_CPUM_SF_DIAG     0xBD000 /* Event: Combined-sampling */
0016 #define DEFAULT_AUX_PAGES       128
0017 #define DEFAULT_FREQ            4000
0018 
0019 static void cpumsf_free(struct auxtrace_record *itr)
0020 {
0021     free(itr);
0022 }
0023 
0024 static size_t cpumsf_info_priv_size(struct auxtrace_record *itr __maybe_unused,
0025                     struct evlist *evlist __maybe_unused)
0026 {
0027     return 0;
0028 }
0029 
0030 static int
0031 cpumsf_info_fill(struct auxtrace_record *itr __maybe_unused,
0032          struct perf_session *session __maybe_unused,
0033          struct perf_record_auxtrace_info *auxtrace_info __maybe_unused,
0034          size_t priv_size __maybe_unused)
0035 {
0036     auxtrace_info->type = PERF_AUXTRACE_S390_CPUMSF;
0037     return 0;
0038 }
0039 
0040 static unsigned long
0041 cpumsf_reference(struct auxtrace_record *itr __maybe_unused)
0042 {
0043     return 0;
0044 }
0045 
0046 static int
0047 cpumsf_recording_options(struct auxtrace_record *ar __maybe_unused,
0048              struct evlist *evlist __maybe_unused,
0049              struct record_opts *opts)
0050 {
0051     unsigned int factor = 1;
0052     unsigned int pages;
0053 
0054     opts->full_auxtrace = true;
0055 
0056     /*
0057      * The AUX buffer size should be set properly to avoid
0058      * overflow of samples if it is not set explicitly.
0059      * DEFAULT_AUX_PAGES is an proper size when sampling frequency
0060      * is DEFAULT_FREQ. It is expected to hold about 1/2 second
0061      * of sampling data. The size used for AUX buffer will scale
0062      * according to the specified frequency and DEFAULT_FREQ.
0063      */
0064     if (!opts->auxtrace_mmap_pages) {
0065         if (opts->user_freq != UINT_MAX)
0066             factor = (opts->user_freq + DEFAULT_FREQ
0067                   - 1) / DEFAULT_FREQ;
0068         pages = DEFAULT_AUX_PAGES * factor;
0069         opts->auxtrace_mmap_pages = roundup_pow_of_two(pages);
0070     }
0071 
0072     return 0;
0073 }
0074 
0075 static int
0076 cpumsf_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
0077                   struct record_opts *opts __maybe_unused,
0078                   const char *str __maybe_unused)
0079 {
0080     return 0;
0081 }
0082 
0083 /*
0084  * auxtrace_record__init is called when perf record
0085  * check if the event really need auxtrace
0086  */
0087 struct auxtrace_record *auxtrace_record__init(struct evlist *evlist,
0088                           int *err)
0089 {
0090     struct auxtrace_record *aux;
0091     struct evsel *pos;
0092     int diagnose = 0;
0093 
0094     *err = 0;
0095     if (evlist->core.nr_entries == 0)
0096         return NULL;
0097 
0098     evlist__for_each_entry(evlist, pos) {
0099         if (pos->core.attr.config == PERF_EVENT_CPUM_SF_DIAG) {
0100             diagnose = 1;
0101             pos->needs_auxtrace_mmap = true;
0102             break;
0103         }
0104     }
0105 
0106     if (!diagnose)
0107         return NULL;
0108 
0109     /* sampling in diagnose mode. alloc aux buffer */
0110     aux = zalloc(sizeof(*aux));
0111     if (aux == NULL) {
0112         *err = -ENOMEM;
0113         return NULL;
0114     }
0115 
0116     aux->parse_snapshot_options = cpumsf_parse_snapshot_options;
0117     aux->recording_options = cpumsf_recording_options;
0118     aux->info_priv_size = cpumsf_info_priv_size;
0119     aux->info_fill = cpumsf_info_fill;
0120     aux->free = cpumsf_free;
0121     aux->reference = cpumsf_reference;
0122 
0123     return aux;
0124 }