hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/lib/stackdepot.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Generic stack depot for storing stack traces.
34 *
....@@ -16,19 +17,10 @@
1617 * Copyright (C) 2016 Google, Inc.
1718 *
1819 * Based on code by Dmitry Chernenkov.
19
- *
20
- * This program is free software; you can redistribute it and/or
21
- * modify it under the terms of the GNU General Public License
22
- * version 2 as published by the Free Software Foundation.
23
- *
24
- * This program is distributed in the hope that it will be useful, but
25
- * WITHOUT ANY WARRANTY; without even the implied warranty of
26
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27
- * General Public License for more details.
28
- *
2920 */
3021
3122 #include <linux/gfp.h>
23
+#include <linux/interrupt.h>
3224 #include <linux/jhash.h>
3325 #include <linux/kernel.h>
3426 #include <linux/mm.h>
....@@ -39,6 +31,7 @@
3931 #include <linux/stackdepot.h>
4032 #include <linux/string.h>
4133 #include <linux/types.h>
34
+#include <linux/memblock.h>
4235
4336 #define DEPOT_STACK_BITS (sizeof(depot_stack_handle_t) * 8)
4437
....@@ -70,7 +63,7 @@
7063 u32 hash; /* Hash in the hastable */
7164 u32 size; /* Number of frames in the stack */
7265 union handle_parts handle;
73
- unsigned long entries[1]; /* Variable-sized array of entries. */
66
+ unsigned long entries[]; /* Variable-sized array of entries. */
7467 };
7568
7669 static void *stack_slabs[STACK_ALLOC_MAX_SLABS];
....@@ -101,7 +94,7 @@
10194 }
10295 /*
10396 * This smp_store_release pairs with smp_load_acquire() from
104
- * |next_slab_inited| above and in depot_save_stack().
97
+ * |next_slab_inited| above and in stack_depot_save().
10598 */
10699 smp_store_release(&next_slab_inited, 1);
107100 }
....@@ -112,9 +105,8 @@
112105 static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
113106 u32 hash, void **prealloc, gfp_t alloc_flags)
114107 {
115
- int required_size = offsetof(struct stack_record, entries) +
116
- sizeof(unsigned long) * size;
117108 struct stack_record *stack;
109
+ size_t required_size = struct_size(stack, entries, size);
118110
119111 required_size = ALIGN(required_size, 1 << STACK_ALLOC_ALIGN);
120112
....@@ -127,7 +119,7 @@
127119 depot_offset = 0;
128120 /*
129121 * smp_store_release() here pairs with smp_load_acquire() from
130
- * |next_slab_inited| in depot_save_stack() and
122
+ * |next_slab_inited| in stack_depot_save() and
131123 * init_stack_slab().
132124 */
133125 if (depot_index + 1 < STACK_ALLOC_MAX_SLABS)
....@@ -144,27 +136,51 @@
144136 stack->handle.slabindex = depot_index;
145137 stack->handle.offset = depot_offset >> STACK_ALLOC_ALIGN;
146138 stack->handle.valid = 1;
147
- memcpy(stack->entries, entries, size * sizeof(unsigned long));
139
+ memcpy(stack->entries, entries, flex_array_size(stack, entries, size));
148140 depot_offset += required_size;
149141
150142 return stack;
151143 }
152144
153
-#define STACK_HASH_ORDER 20
154
-#define STACK_HASH_SIZE (1L << STACK_HASH_ORDER)
145
+#define STACK_HASH_SIZE (1L << CONFIG_STACK_HASH_ORDER)
155146 #define STACK_HASH_MASK (STACK_HASH_SIZE - 1)
156147 #define STACK_HASH_SEED 0x9747b28c
157148
158
-static struct stack_record *stack_table[STACK_HASH_SIZE] = {
159
- [0 ... STACK_HASH_SIZE - 1] = NULL
160
-};
149
+static bool stack_depot_disable;
150
+static struct stack_record **stack_table;
151
+
152
+static int __init is_stack_depot_disabled(char *str)
153
+{
154
+ int ret;
155
+
156
+ ret = kstrtobool(str, &stack_depot_disable);
157
+ if (!ret && stack_depot_disable) {
158
+ pr_info("Stack Depot is disabled\n");
159
+ stack_table = NULL;
160
+ }
161
+ return 0;
162
+}
163
+early_param("stack_depot_disable", is_stack_depot_disabled);
164
+
165
+int __init stack_depot_init(void)
166
+{
167
+ if (!stack_depot_disable) {
168
+ size_t size = (STACK_HASH_SIZE * sizeof(struct stack_record *));
169
+ int i;
170
+
171
+ stack_table = memblock_alloc(size, size);
172
+ for (i = 0; i < STACK_HASH_SIZE; i++)
173
+ stack_table[i] = NULL;
174
+ }
175
+ return 0;
176
+}
161177
162178 /* Calculate hash for a stack */
163179 static inline u32 hash_stack(unsigned long *entries, unsigned int size)
164180 {
165181 return jhash2((u32 *)entries,
166
- size * sizeof(unsigned long) / sizeof(u32),
167
- STACK_HASH_SEED);
182
+ array_size(size, sizeof(*entries)) / sizeof(u32),
183
+ STACK_HASH_SEED);
168184 }
169185
170186 /* Use our own, non-instrumented version of memcmp().
....@@ -198,40 +214,63 @@
198214 return NULL;
199215 }
200216
201
-void depot_fetch_stack(depot_stack_handle_t handle, struct stack_trace *trace)
217
+/**
218
+ * stack_depot_fetch - Fetch stack entries from a depot
219
+ *
220
+ * @handle: Stack depot handle which was returned from
221
+ * stack_depot_save().
222
+ * @entries: Pointer to store the entries address
223
+ *
224
+ * Return: The number of trace entries for this depot.
225
+ */
226
+unsigned int stack_depot_fetch(depot_stack_handle_t handle,
227
+ unsigned long **entries)
202228 {
203229 union handle_parts parts = { .handle = handle };
204
- void *slab = stack_slabs[parts.slabindex];
230
+ void *slab;
205231 size_t offset = parts.offset << STACK_ALLOC_ALIGN;
206
- struct stack_record *stack = slab + offset;
232
+ struct stack_record *stack;
207233
208
- trace->nr_entries = trace->max_entries = stack->size;
209
- trace->entries = stack->entries;
210
- trace->skip = 0;
234
+ *entries = NULL;
235
+ if (parts.slabindex > depot_index) {
236
+ WARN(1, "slab index %d out of bounds (%d) for stack id %08x\n",
237
+ parts.slabindex, depot_index, handle);
238
+ return 0;
239
+ }
240
+ slab = stack_slabs[parts.slabindex];
241
+ if (!slab)
242
+ return 0;
243
+ stack = slab + offset;
244
+
245
+ *entries = stack->entries;
246
+ return stack->size;
211247 }
212
-EXPORT_SYMBOL_GPL(depot_fetch_stack);
248
+EXPORT_SYMBOL_GPL(stack_depot_fetch);
213249
214250 /**
215
- * depot_save_stack - save stack in a stack depot.
216
- * @trace - the stacktrace to save.
217
- * @alloc_flags - flags for allocating additional memory if required.
251
+ * stack_depot_save - Save a stack trace from an array
218252 *
219
- * Returns the handle of the stack struct stored in depot.
253
+ * @entries: Pointer to storage array
254
+ * @nr_entries: Size of the storage array
255
+ * @alloc_flags: Allocation gfp flags
256
+ *
257
+ * Return: The handle of the stack struct stored in depot
220258 */
221
-depot_stack_handle_t depot_save_stack(struct stack_trace *trace,
222
- gfp_t alloc_flags)
259
+depot_stack_handle_t stack_depot_save(unsigned long *entries,
260
+ unsigned int nr_entries,
261
+ gfp_t alloc_flags)
223262 {
224
- u32 hash;
225
- depot_stack_handle_t retval = 0;
226263 struct stack_record *found = NULL, **bucket;
227
- unsigned long flags;
264
+ depot_stack_handle_t retval = 0;
228265 struct page *page = NULL;
229266 void *prealloc = NULL;
267
+ unsigned long flags;
268
+ u32 hash;
230269
231
- if (unlikely(trace->nr_entries == 0))
270
+ if (unlikely(nr_entries == 0) || stack_depot_disable)
232271 goto fast_exit;
233272
234
- hash = hash_stack(trace->entries, trace->nr_entries);
273
+ hash = hash_stack(entries, nr_entries);
235274 bucket = &stack_table[hash & STACK_HASH_MASK];
236275
237276 /*
....@@ -239,8 +278,8 @@
239278 * The smp_load_acquire() here pairs with smp_store_release() to
240279 * |bucket| below.
241280 */
242
- found = find_stack(smp_load_acquire(bucket), trace->entries,
243
- trace->nr_entries, hash);
281
+ found = find_stack(smp_load_acquire(bucket), entries,
282
+ nr_entries, hash);
244283 if (found)
245284 goto exit;
246285
....@@ -268,10 +307,10 @@
268307
269308 raw_spin_lock_irqsave(&depot_lock, flags);
270309
271
- found = find_stack(*bucket, trace->entries, trace->nr_entries, hash);
310
+ found = find_stack(*bucket, entries, nr_entries, hash);
272311 if (!found) {
273312 struct stack_record *new =
274
- depot_alloc_stack(trace->entries, trace->nr_entries,
313
+ depot_alloc_stack(entries, nr_entries,
275314 hash, &prealloc, alloc_flags);
276315 if (new) {
277316 new->next = *bucket;
....@@ -301,4 +340,27 @@
301340 fast_exit:
302341 return retval;
303342 }
304
-EXPORT_SYMBOL_GPL(depot_save_stack);
343
+EXPORT_SYMBOL_GPL(stack_depot_save);
344
+
345
+static inline int in_irqentry_text(unsigned long ptr)
346
+{
347
+ return (ptr >= (unsigned long)&__irqentry_text_start &&
348
+ ptr < (unsigned long)&__irqentry_text_end) ||
349
+ (ptr >= (unsigned long)&__softirqentry_text_start &&
350
+ ptr < (unsigned long)&__softirqentry_text_end);
351
+}
352
+
353
+unsigned int filter_irq_stacks(unsigned long *entries,
354
+ unsigned int nr_entries)
355
+{
356
+ unsigned int i;
357
+
358
+ for (i = 0; i < nr_entries; i++) {
359
+ if (in_irqentry_text(entries[i])) {
360
+ /* Include the irqentry function into the stack. */
361
+ return i + 1;
362
+ }
363
+ }
364
+ return nr_entries;
365
+}
366
+EXPORT_SYMBOL_GPL(filter_irq_stacks);