1 #include <stdbool.h> 2 #include <linux/kernel.h> 3 #include <linux/types.h> 4 #include <linux/bitops.h> 5 #include <linux/log2.h> 6 #include <linux/zalloc.h> 7 8 #include "../../util/evlist.h" 9 #include "../../util/auxtrace.h" 10 #include "../../util/evsel.h" 11 12 #define PERF_EVENT_CPUM_SF 0xB0000 /* Event: Basic-sampling */ 13 #define PERF_EVENT_CPUM_SF_DIAG 0xBD000 /* Event: Combined-sampling */ 14 #define DEFAULT_AUX_PAGES 128 15 #define DEFAULT_FREQ 4000 16 17 static void cpumsf_free(struct auxtrace_record *itr) 18 { 19 free(itr); 20 } 21 22 static size_t cpumsf_info_priv_size(struct auxtrace_record *itr __maybe_unused, 23 struct perf_evlist *evlist __maybe_unused) 24 { 25 return 0; 26 } 27 28 static int 29 cpumsf_info_fill(struct auxtrace_record *itr __maybe_unused, 30 struct perf_session *session __maybe_unused, 31 struct auxtrace_info_event *auxtrace_info __maybe_unused, 32 size_t priv_size __maybe_unused) 33 { 34 auxtrace_info->type = PERF_AUXTRACE_S390_CPUMSF; 35 return 0; 36 } 37 38 static unsigned long 39 cpumsf_reference(struct auxtrace_record *itr __maybe_unused) 40 { 41 return 0; 42 } 43 44 static int 45 cpumsf_recording_options(struct auxtrace_record *ar __maybe_unused, 46 struct perf_evlist *evlist __maybe_unused, 47 struct record_opts *opts) 48 { 49 unsigned int factor = 1; 50 unsigned int pages; 51 52 opts->full_auxtrace = true; 53 54 /* 55 * The AUX buffer size should be set properly to avoid 56 * overflow of samples if it is not set explicitly. 57 * DEFAULT_AUX_PAGES is an proper size when sampling frequency 58 * is DEFAULT_FREQ. It is expected to hold about 1/2 second 59 * of sampling data. The size used for AUX buffer will scale 60 * according to the specified frequency and DEFAULT_FREQ. 61 */ 62 if (!opts->auxtrace_mmap_pages) { 63 if (opts->user_freq != UINT_MAX) 64 factor = (opts->user_freq + DEFAULT_FREQ 65 - 1) / DEFAULT_FREQ; 66 pages = DEFAULT_AUX_PAGES * factor; 67 opts->auxtrace_mmap_pages = roundup_pow_of_two(pages); 68 } 69 70 return 0; 71 } 72 73 static int 74 cpumsf_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused, 75 struct record_opts *opts __maybe_unused, 76 const char *str __maybe_unused) 77 { 78 return 0; 79 } 80 81 /* 82 * auxtrace_record__init is called when perf record 83 * check if the event really need auxtrace 84 */ 85 struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist, 86 int *err) 87 { 88 struct auxtrace_record *aux; 89 struct perf_evsel *pos; 90 int diagnose = 0; 91 92 *err = 0; 93 if (evlist->nr_entries == 0) 94 return NULL; 95 96 evlist__for_each_entry(evlist, pos) { 97 if (pos->attr.config == PERF_EVENT_CPUM_SF_DIAG) { 98 diagnose = 1; 99 break; 100 } 101 } 102 103 if (!diagnose) 104 return NULL; 105 106 /* sampling in diagnose mode. alloc aux buffer */ 107 aux = zalloc(sizeof(*aux)); 108 if (aux == NULL) { 109 *err = -ENOMEM; 110 return NULL; 111 } 112 113 aux->parse_snapshot_options = cpumsf_parse_snapshot_options; 114 aux->recording_options = cpumsf_recording_options; 115 aux->info_priv_size = cpumsf_info_priv_size; 116 aux->info_fill = cpumsf_info_fill; 117 aux->free = cpumsf_free; 118 aux->reference = cpumsf_reference; 119 120 return aux; 121 } 122