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
0015 #define PERF_EVENT_CPUM_SF_DIAG 0xBD000
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
0058
0059
0060
0061
0062
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
0085
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
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 }