1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * VPA support
4 */
5
6 #include <linux/kernel.h>
7 #include <linux/types.h>
8 #include <linux/string.h>
9
10 #include "../../util/evlist.h"
11 #include "../../util/debug.h"
12 #include "../../util/auxtrace.h"
13 #include "../../util/powerpc-vpadtl.h"
14 #include "../../util/record.h"
15 #include <internal/lib.h> // page_size
16
17 #define KiB(x) ((x) * 1024)
18
19 static int
powerpc_vpadtl_recording_options(struct auxtrace_record * ar __maybe_unused,struct evlist * evlist __maybe_unused,struct record_opts * opts)20 powerpc_vpadtl_recording_options(struct auxtrace_record *ar __maybe_unused,
21 struct evlist *evlist __maybe_unused,
22 struct record_opts *opts)
23 {
24 opts->full_auxtrace = true;
25
26 /*
27 * Set auxtrace_mmap_pages to minimum
28 * two pages
29 */
30 if (!opts->auxtrace_mmap_pages) {
31 opts->auxtrace_mmap_pages = KiB(128) / page_size;
32 if (opts->mmap_pages == UINT_MAX)
33 opts->mmap_pages = KiB(256) / page_size;
34 }
35
36 return 0;
37 }
38
powerpc_vpadtl_info_priv_size(struct auxtrace_record * itr __maybe_unused,struct evlist * evlist __maybe_unused)39 static size_t powerpc_vpadtl_info_priv_size(struct auxtrace_record *itr __maybe_unused,
40 struct evlist *evlist __maybe_unused)
41 {
42 return VPADTL_AUXTRACE_PRIV_SIZE;
43 }
44
45 static int
powerpc_vpadtl_info_fill(struct auxtrace_record * itr __maybe_unused,struct perf_session * session __maybe_unused,struct perf_record_auxtrace_info * auxtrace_info,size_t priv_size __maybe_unused)46 powerpc_vpadtl_info_fill(struct auxtrace_record *itr __maybe_unused,
47 struct perf_session *session __maybe_unused,
48 struct perf_record_auxtrace_info *auxtrace_info,
49 size_t priv_size __maybe_unused)
50 {
51 auxtrace_info->type = PERF_AUXTRACE_VPA_DTL;
52
53 return 0;
54 }
55
powerpc_vpadtl_free(struct auxtrace_record * itr)56 static void powerpc_vpadtl_free(struct auxtrace_record *itr)
57 {
58 free(itr);
59 }
60
powerpc_vpadtl_reference(struct auxtrace_record * itr __maybe_unused)61 static u64 powerpc_vpadtl_reference(struct auxtrace_record *itr __maybe_unused)
62 {
63 return 0;
64 }
65
auxtrace_record__init(struct evlist * evlist,int * err)66 struct auxtrace_record *auxtrace_record__init(struct evlist *evlist,
67 int *err)
68 {
69 struct auxtrace_record *aux;
70 struct evsel *pos;
71 int found = 0;
72
73 evlist__for_each_entry(evlist, pos) {
74 if (strstarts(pos->name, "vpa_dtl")) {
75 found = 1;
76 pos->needs_auxtrace_mmap = true;
77 break;
78 }
79 }
80
81 if (!found)
82 return NULL;
83
84 /*
85 * To obtain the auxtrace buffer file descriptor, the auxtrace event
86 * must come first.
87 */
88 evlist__to_front(pos->evlist, pos);
89
90 aux = zalloc(sizeof(*aux));
91 if (aux == NULL) {
92 pr_debug("aux record is NULL\n");
93 *err = -ENOMEM;
94 return NULL;
95 }
96
97 aux->recording_options = powerpc_vpadtl_recording_options;
98 aux->info_priv_size = powerpc_vpadtl_info_priv_size;
99 aux->info_fill = powerpc_vpadtl_info_fill;
100 aux->free = powerpc_vpadtl_free;
101 aux->reference = powerpc_vpadtl_reference;
102 return aux;
103 }
104