drm/panthor: Don't add write fences to the shared BOs
[drm/drm-misc.git] / lib / alloc_tag.c
blob81e5f9a70f22076f3ede3c2412ae152f48f34ee7
1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/alloc_tag.h>
3 #include <linux/fs.h>
4 #include <linux/gfp.h>
5 #include <linux/module.h>
6 #include <linux/page_ext.h>
7 #include <linux/proc_fs.h>
8 #include <linux/seq_buf.h>
9 #include <linux/seq_file.h>
11 static struct codetag_type *alloc_tag_cttype;
13 DEFINE_PER_CPU(struct alloc_tag_counters, _shared_alloc_tag);
14 EXPORT_SYMBOL(_shared_alloc_tag);
16 DEFINE_STATIC_KEY_MAYBE(CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT,
17 mem_alloc_profiling_key);
19 struct allocinfo_private {
20 struct codetag_iterator iter;
21 bool print_header;
24 static void *allocinfo_start(struct seq_file *m, loff_t *pos)
26 struct allocinfo_private *priv;
27 struct codetag *ct;
28 loff_t node = *pos;
30 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
31 m->private = priv;
32 if (!priv)
33 return NULL;
35 priv->print_header = (node == 0);
36 codetag_lock_module_list(alloc_tag_cttype, true);
37 priv->iter = codetag_get_ct_iter(alloc_tag_cttype);
38 while ((ct = codetag_next_ct(&priv->iter)) != NULL && node)
39 node--;
41 return ct ? priv : NULL;
44 static void *allocinfo_next(struct seq_file *m, void *arg, loff_t *pos)
46 struct allocinfo_private *priv = (struct allocinfo_private *)arg;
47 struct codetag *ct = codetag_next_ct(&priv->iter);
49 (*pos)++;
50 if (!ct)
51 return NULL;
53 return priv;
56 static void allocinfo_stop(struct seq_file *m, void *arg)
58 struct allocinfo_private *priv = (struct allocinfo_private *)m->private;
60 if (priv) {
61 codetag_lock_module_list(alloc_tag_cttype, false);
62 kfree(priv);
66 static void print_allocinfo_header(struct seq_buf *buf)
68 /* Output format version, so we can change it. */
69 seq_buf_printf(buf, "allocinfo - version: 1.0\n");
70 seq_buf_printf(buf, "# <size> <calls> <tag info>\n");
73 static void alloc_tag_to_text(struct seq_buf *out, struct codetag *ct)
75 struct alloc_tag *tag = ct_to_alloc_tag(ct);
76 struct alloc_tag_counters counter = alloc_tag_read(tag);
77 s64 bytes = counter.bytes;
79 seq_buf_printf(out, "%12lli %8llu ", bytes, counter.calls);
80 codetag_to_text(out, ct);
81 seq_buf_putc(out, ' ');
82 seq_buf_putc(out, '\n');
85 static int allocinfo_show(struct seq_file *m, void *arg)
87 struct allocinfo_private *priv = (struct allocinfo_private *)arg;
88 char *bufp;
89 size_t n = seq_get_buf(m, &bufp);
90 struct seq_buf buf;
92 seq_buf_init(&buf, bufp, n);
93 if (priv->print_header) {
94 print_allocinfo_header(&buf);
95 priv->print_header = false;
97 alloc_tag_to_text(&buf, priv->iter.ct);
98 seq_commit(m, seq_buf_used(&buf));
99 return 0;
102 static const struct seq_operations allocinfo_seq_op = {
103 .start = allocinfo_start,
104 .next = allocinfo_next,
105 .stop = allocinfo_stop,
106 .show = allocinfo_show,
109 size_t alloc_tag_top_users(struct codetag_bytes *tags, size_t count, bool can_sleep)
111 struct codetag_iterator iter;
112 struct codetag *ct;
113 struct codetag_bytes n;
114 unsigned int i, nr = 0;
116 if (can_sleep)
117 codetag_lock_module_list(alloc_tag_cttype, true);
118 else if (!codetag_trylock_module_list(alloc_tag_cttype))
119 return 0;
121 iter = codetag_get_ct_iter(alloc_tag_cttype);
122 while ((ct = codetag_next_ct(&iter))) {
123 struct alloc_tag_counters counter = alloc_tag_read(ct_to_alloc_tag(ct));
125 n.ct = ct;
126 n.bytes = counter.bytes;
128 for (i = 0; i < nr; i++)
129 if (n.bytes > tags[i].bytes)
130 break;
132 if (i < count) {
133 nr -= nr == count;
134 memmove(&tags[i + 1],
135 &tags[i],
136 sizeof(tags[0]) * (nr - i));
137 nr++;
138 tags[i] = n;
142 codetag_lock_module_list(alloc_tag_cttype, false);
144 return nr;
147 static void __init procfs_init(void)
149 proc_create_seq("allocinfo", 0400, NULL, &allocinfo_seq_op);
152 static bool alloc_tag_module_unload(struct codetag_type *cttype,
153 struct codetag_module *cmod)
155 struct codetag_iterator iter = codetag_get_ct_iter(cttype);
156 struct alloc_tag_counters counter;
157 bool module_unused = true;
158 struct alloc_tag *tag;
159 struct codetag *ct;
161 for (ct = codetag_next_ct(&iter); ct; ct = codetag_next_ct(&iter)) {
162 if (iter.cmod != cmod)
163 continue;
165 tag = ct_to_alloc_tag(ct);
166 counter = alloc_tag_read(tag);
168 if (WARN(counter.bytes,
169 "%s:%u module %s func:%s has %llu allocated at module unload",
170 ct->filename, ct->lineno, ct->modname, ct->function, counter.bytes))
171 module_unused = false;
174 return module_unused;
177 #ifdef CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT
178 static bool mem_profiling_support __meminitdata = true;
179 #else
180 static bool mem_profiling_support __meminitdata;
181 #endif
183 static int __init setup_early_mem_profiling(char *str)
185 bool enable;
187 if (!str || !str[0])
188 return -EINVAL;
190 if (!strncmp(str, "never", 5)) {
191 enable = false;
192 mem_profiling_support = false;
193 } else {
194 int res;
196 res = kstrtobool(str, &enable);
197 if (res)
198 return res;
200 mem_profiling_support = true;
203 if (enable != static_key_enabled(&mem_alloc_profiling_key)) {
204 if (enable)
205 static_branch_enable(&mem_alloc_profiling_key);
206 else
207 static_branch_disable(&mem_alloc_profiling_key);
210 return 0;
212 early_param("sysctl.vm.mem_profiling", setup_early_mem_profiling);
214 static __init bool need_page_alloc_tagging(void)
216 return mem_profiling_support;
219 static __init void init_page_alloc_tagging(void)
223 struct page_ext_operations page_alloc_tagging_ops = {
224 .size = sizeof(union codetag_ref),
225 .need = need_page_alloc_tagging,
226 .init = init_page_alloc_tagging,
228 EXPORT_SYMBOL(page_alloc_tagging_ops);
230 #ifdef CONFIG_SYSCTL
231 static struct ctl_table memory_allocation_profiling_sysctls[] = {
233 .procname = "mem_profiling",
234 .data = &mem_alloc_profiling_key,
235 #ifdef CONFIG_MEM_ALLOC_PROFILING_DEBUG
236 .mode = 0444,
237 #else
238 .mode = 0644,
239 #endif
240 .proc_handler = proc_do_static_key,
244 static void __init sysctl_init(void)
246 if (!mem_profiling_support)
247 memory_allocation_profiling_sysctls[0].mode = 0444;
249 register_sysctl_init("vm", memory_allocation_profiling_sysctls);
251 #else /* CONFIG_SYSCTL */
252 static inline void sysctl_init(void) {}
253 #endif /* CONFIG_SYSCTL */
255 static int __init alloc_tag_init(void)
257 const struct codetag_type_desc desc = {
258 .section = "alloc_tags",
259 .tag_size = sizeof(struct alloc_tag),
260 .module_unload = alloc_tag_module_unload,
263 alloc_tag_cttype = codetag_register_type(&desc);
264 if (IS_ERR(alloc_tag_cttype))
265 return PTR_ERR(alloc_tag_cttype);
267 sysctl_init();
268 procfs_init();
270 return 0;
272 module_init(alloc_tag_init);