xref: /kernel/linux/linux-6.6/lib/stackdepot.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Stack depot - a stack trace storage that avoids duplication.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Internally, stack depot maintains a hash table of unique stacktraces. The
662306a36Sopenharmony_ci * stack traces themselves are stored contiguously one after another in a set
762306a36Sopenharmony_ci * of separate page allocations.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Author: Alexander Potapenko <glider@google.com>
1062306a36Sopenharmony_ci * Copyright (C) 2016 Google, Inc.
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * Based on the code by Dmitry Chernenkov.
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define pr_fmt(fmt) "stackdepot: " fmt
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/gfp.h>
1862306a36Sopenharmony_ci#include <linux/jhash.h>
1962306a36Sopenharmony_ci#include <linux/kernel.h>
2062306a36Sopenharmony_ci#include <linux/kmsan.h>
2162306a36Sopenharmony_ci#include <linux/mm.h>
2262306a36Sopenharmony_ci#include <linux/mutex.h>
2362306a36Sopenharmony_ci#include <linux/percpu.h>
2462306a36Sopenharmony_ci#include <linux/printk.h>
2562306a36Sopenharmony_ci#include <linux/slab.h>
2662306a36Sopenharmony_ci#include <linux/stacktrace.h>
2762306a36Sopenharmony_ci#include <linux/stackdepot.h>
2862306a36Sopenharmony_ci#include <linux/string.h>
2962306a36Sopenharmony_ci#include <linux/types.h>
3062306a36Sopenharmony_ci#include <linux/memblock.h>
3162306a36Sopenharmony_ci#include <linux/kasan-enabled.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define DEPOT_HANDLE_BITS (sizeof(depot_stack_handle_t) * 8)
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define DEPOT_VALID_BITS 1
3662306a36Sopenharmony_ci#define DEPOT_POOL_ORDER 2 /* Pool size order, 4 pages */
3762306a36Sopenharmony_ci#define DEPOT_POOL_SIZE (1LL << (PAGE_SHIFT + DEPOT_POOL_ORDER))
3862306a36Sopenharmony_ci#define DEPOT_STACK_ALIGN 4
3962306a36Sopenharmony_ci#define DEPOT_OFFSET_BITS (DEPOT_POOL_ORDER + PAGE_SHIFT - DEPOT_STACK_ALIGN)
4062306a36Sopenharmony_ci#define DEPOT_POOL_INDEX_BITS (DEPOT_HANDLE_BITS - DEPOT_VALID_BITS - \
4162306a36Sopenharmony_ci			       DEPOT_OFFSET_BITS - STACK_DEPOT_EXTRA_BITS)
4262306a36Sopenharmony_ci#define DEPOT_POOLS_CAP 8192
4362306a36Sopenharmony_ci#define DEPOT_MAX_POOLS \
4462306a36Sopenharmony_ci	(((1LL << (DEPOT_POOL_INDEX_BITS)) < DEPOT_POOLS_CAP) ? \
4562306a36Sopenharmony_ci	 (1LL << (DEPOT_POOL_INDEX_BITS)) : DEPOT_POOLS_CAP)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* Compact structure that stores a reference to a stack. */
4862306a36Sopenharmony_ciunion handle_parts {
4962306a36Sopenharmony_ci	depot_stack_handle_t handle;
5062306a36Sopenharmony_ci	struct {
5162306a36Sopenharmony_ci		u32 pool_index	: DEPOT_POOL_INDEX_BITS;
5262306a36Sopenharmony_ci		u32 offset	: DEPOT_OFFSET_BITS;
5362306a36Sopenharmony_ci		u32 valid	: DEPOT_VALID_BITS;
5462306a36Sopenharmony_ci		u32 extra	: STACK_DEPOT_EXTRA_BITS;
5562306a36Sopenharmony_ci	};
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistruct stack_record {
5962306a36Sopenharmony_ci	struct stack_record *next;	/* Link in the hash table */
6062306a36Sopenharmony_ci	u32 hash;			/* Hash in the hash table */
6162306a36Sopenharmony_ci	u32 size;			/* Number of stored frames */
6262306a36Sopenharmony_ci	union handle_parts handle;
6362306a36Sopenharmony_ci	unsigned long entries[];	/* Variable-sized array of frames */
6462306a36Sopenharmony_ci};
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic bool stack_depot_disabled;
6762306a36Sopenharmony_cistatic bool __stack_depot_early_init_requested __initdata = IS_ENABLED(CONFIG_STACKDEPOT_ALWAYS_INIT);
6862306a36Sopenharmony_cistatic bool __stack_depot_early_init_passed __initdata;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/* Use one hash table bucket per 16 KB of memory. */
7162306a36Sopenharmony_ci#define STACK_HASH_TABLE_SCALE 14
7262306a36Sopenharmony_ci/* Limit the number of buckets between 4K and 1M. */
7362306a36Sopenharmony_ci#define STACK_BUCKET_NUMBER_ORDER_MIN 12
7462306a36Sopenharmony_ci#define STACK_BUCKET_NUMBER_ORDER_MAX 20
7562306a36Sopenharmony_ci/* Initial seed for jhash2. */
7662306a36Sopenharmony_ci#define STACK_HASH_SEED 0x9747b28c
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/* Hash table of pointers to stored stack traces. */
7962306a36Sopenharmony_cistatic struct stack_record **stack_table;
8062306a36Sopenharmony_ci/* Fixed order of the number of table buckets. Used when KASAN is enabled. */
8162306a36Sopenharmony_cistatic unsigned int stack_bucket_number_order;
8262306a36Sopenharmony_ci/* Hash mask for indexing the table. */
8362306a36Sopenharmony_cistatic unsigned int stack_hash_mask;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci/* Array of memory regions that store stack traces. */
8662306a36Sopenharmony_cistatic void *stack_pools[DEPOT_MAX_POOLS];
8762306a36Sopenharmony_ci/* Currently used pool in stack_pools. */
8862306a36Sopenharmony_cistatic int pool_index;
8962306a36Sopenharmony_ci/* Offset to the unused space in the currently used pool. */
9062306a36Sopenharmony_cistatic size_t pool_offset;
9162306a36Sopenharmony_ci/* Lock that protects the variables above. */
9262306a36Sopenharmony_cistatic DEFINE_RAW_SPINLOCK(pool_lock);
9362306a36Sopenharmony_ci/*
9462306a36Sopenharmony_ci * Stack depot tries to keep an extra pool allocated even before it runs out
9562306a36Sopenharmony_ci * of space in the currently used pool.
9662306a36Sopenharmony_ci * This flag marks that this next extra pool needs to be allocated and
9762306a36Sopenharmony_ci * initialized. It has the value 0 when either the next pool is not yet
9862306a36Sopenharmony_ci * initialized or the limit on the number of pools is reached.
9962306a36Sopenharmony_ci */
10062306a36Sopenharmony_cistatic int next_pool_required = 1;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistatic int __init disable_stack_depot(char *str)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	int ret;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	ret = kstrtobool(str, &stack_depot_disabled);
10762306a36Sopenharmony_ci	if (!ret && stack_depot_disabled) {
10862306a36Sopenharmony_ci		pr_info("disabled\n");
10962306a36Sopenharmony_ci		stack_table = NULL;
11062306a36Sopenharmony_ci	}
11162306a36Sopenharmony_ci	return 0;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ciearly_param("stack_depot_disable", disable_stack_depot);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_civoid __init stack_depot_request_early_init(void)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	/* Too late to request early init now. */
11862306a36Sopenharmony_ci	WARN_ON(__stack_depot_early_init_passed);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	__stack_depot_early_init_requested = true;
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci/* Allocates a hash table via memblock. Can only be used during early boot. */
12462306a36Sopenharmony_ciint __init stack_depot_early_init(void)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	unsigned long entries = 0;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	/* This function must be called only once, from mm_init(). */
12962306a36Sopenharmony_ci	if (WARN_ON(__stack_depot_early_init_passed))
13062306a36Sopenharmony_ci		return 0;
13162306a36Sopenharmony_ci	__stack_depot_early_init_passed = true;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	/*
13462306a36Sopenharmony_ci	 * If KASAN is enabled, use the maximum order: KASAN is frequently used
13562306a36Sopenharmony_ci	 * in fuzzing scenarios, which leads to a large number of different
13662306a36Sopenharmony_ci	 * stack traces being stored in stack depot.
13762306a36Sopenharmony_ci	 */
13862306a36Sopenharmony_ci	if (kasan_enabled() && !stack_bucket_number_order)
13962306a36Sopenharmony_ci		stack_bucket_number_order = STACK_BUCKET_NUMBER_ORDER_MAX;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	if (!__stack_depot_early_init_requested || stack_depot_disabled)
14262306a36Sopenharmony_ci		return 0;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/*
14562306a36Sopenharmony_ci	 * If stack_bucket_number_order is not set, leave entries as 0 to rely
14662306a36Sopenharmony_ci	 * on the automatic calculations performed by alloc_large_system_hash.
14762306a36Sopenharmony_ci	 */
14862306a36Sopenharmony_ci	if (stack_bucket_number_order)
14962306a36Sopenharmony_ci		entries = 1UL << stack_bucket_number_order;
15062306a36Sopenharmony_ci	pr_info("allocating hash table via alloc_large_system_hash\n");
15162306a36Sopenharmony_ci	stack_table = alloc_large_system_hash("stackdepot",
15262306a36Sopenharmony_ci						sizeof(struct stack_record *),
15362306a36Sopenharmony_ci						entries,
15462306a36Sopenharmony_ci						STACK_HASH_TABLE_SCALE,
15562306a36Sopenharmony_ci						HASH_EARLY | HASH_ZERO,
15662306a36Sopenharmony_ci						NULL,
15762306a36Sopenharmony_ci						&stack_hash_mask,
15862306a36Sopenharmony_ci						1UL << STACK_BUCKET_NUMBER_ORDER_MIN,
15962306a36Sopenharmony_ci						1UL << STACK_BUCKET_NUMBER_ORDER_MAX);
16062306a36Sopenharmony_ci	if (!stack_table) {
16162306a36Sopenharmony_ci		pr_err("hash table allocation failed, disabling\n");
16262306a36Sopenharmony_ci		stack_depot_disabled = true;
16362306a36Sopenharmony_ci		return -ENOMEM;
16462306a36Sopenharmony_ci	}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	return 0;
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci/* Allocates a hash table via kvcalloc. Can be used after boot. */
17062306a36Sopenharmony_ciint stack_depot_init(void)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	static DEFINE_MUTEX(stack_depot_init_mutex);
17362306a36Sopenharmony_ci	unsigned long entries;
17462306a36Sopenharmony_ci	int ret = 0;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	mutex_lock(&stack_depot_init_mutex);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	if (stack_depot_disabled || stack_table)
17962306a36Sopenharmony_ci		goto out_unlock;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	/*
18262306a36Sopenharmony_ci	 * Similarly to stack_depot_early_init, use stack_bucket_number_order
18362306a36Sopenharmony_ci	 * if assigned, and rely on automatic scaling otherwise.
18462306a36Sopenharmony_ci	 */
18562306a36Sopenharmony_ci	if (stack_bucket_number_order) {
18662306a36Sopenharmony_ci		entries = 1UL << stack_bucket_number_order;
18762306a36Sopenharmony_ci	} else {
18862306a36Sopenharmony_ci		int scale = STACK_HASH_TABLE_SCALE;
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci		entries = nr_free_buffer_pages();
19162306a36Sopenharmony_ci		entries = roundup_pow_of_two(entries);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci		if (scale > PAGE_SHIFT)
19462306a36Sopenharmony_ci			entries >>= (scale - PAGE_SHIFT);
19562306a36Sopenharmony_ci		else
19662306a36Sopenharmony_ci			entries <<= (PAGE_SHIFT - scale);
19762306a36Sopenharmony_ci	}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	if (entries < 1UL << STACK_BUCKET_NUMBER_ORDER_MIN)
20062306a36Sopenharmony_ci		entries = 1UL << STACK_BUCKET_NUMBER_ORDER_MIN;
20162306a36Sopenharmony_ci	if (entries > 1UL << STACK_BUCKET_NUMBER_ORDER_MAX)
20262306a36Sopenharmony_ci		entries = 1UL << STACK_BUCKET_NUMBER_ORDER_MAX;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	pr_info("allocating hash table of %lu entries via kvcalloc\n", entries);
20562306a36Sopenharmony_ci	stack_table = kvcalloc(entries, sizeof(struct stack_record *), GFP_KERNEL);
20662306a36Sopenharmony_ci	if (!stack_table) {
20762306a36Sopenharmony_ci		pr_err("hash table allocation failed, disabling\n");
20862306a36Sopenharmony_ci		stack_depot_disabled = true;
20962306a36Sopenharmony_ci		ret = -ENOMEM;
21062306a36Sopenharmony_ci		goto out_unlock;
21162306a36Sopenharmony_ci	}
21262306a36Sopenharmony_ci	stack_hash_mask = entries - 1;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ciout_unlock:
21562306a36Sopenharmony_ci	mutex_unlock(&stack_depot_init_mutex);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	return ret;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stack_depot_init);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci/* Uses preallocated memory to initialize a new stack depot pool. */
22262306a36Sopenharmony_cistatic void depot_init_pool(void **prealloc)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	/*
22562306a36Sopenharmony_ci	 * If the next pool is already initialized or the maximum number of
22662306a36Sopenharmony_ci	 * pools is reached, do not use the preallocated memory.
22762306a36Sopenharmony_ci	 * smp_load_acquire() here pairs with smp_store_release() below and
22862306a36Sopenharmony_ci	 * in depot_alloc_stack().
22962306a36Sopenharmony_ci	 */
23062306a36Sopenharmony_ci	if (!smp_load_acquire(&next_pool_required))
23162306a36Sopenharmony_ci		return;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	/* Check if the current pool is not yet allocated. */
23462306a36Sopenharmony_ci	if (stack_pools[pool_index] == NULL) {
23562306a36Sopenharmony_ci		/* Use the preallocated memory for the current pool. */
23662306a36Sopenharmony_ci		stack_pools[pool_index] = *prealloc;
23762306a36Sopenharmony_ci		*prealloc = NULL;
23862306a36Sopenharmony_ci	} else {
23962306a36Sopenharmony_ci		/*
24062306a36Sopenharmony_ci		 * Otherwise, use the preallocated memory for the next pool
24162306a36Sopenharmony_ci		 * as long as we do not exceed the maximum number of pools.
24262306a36Sopenharmony_ci		 */
24362306a36Sopenharmony_ci		if (pool_index + 1 < DEPOT_MAX_POOLS) {
24462306a36Sopenharmony_ci			stack_pools[pool_index + 1] = *prealloc;
24562306a36Sopenharmony_ci			*prealloc = NULL;
24662306a36Sopenharmony_ci		}
24762306a36Sopenharmony_ci		/*
24862306a36Sopenharmony_ci		 * At this point, either the next pool is initialized or the
24962306a36Sopenharmony_ci		 * maximum number of pools is reached. In either case, take
25062306a36Sopenharmony_ci		 * note that initializing another pool is not required.
25162306a36Sopenharmony_ci		 * This smp_store_release pairs with smp_load_acquire() above
25262306a36Sopenharmony_ci		 * and in stack_depot_save().
25362306a36Sopenharmony_ci		 */
25462306a36Sopenharmony_ci		smp_store_release(&next_pool_required, 0);
25562306a36Sopenharmony_ci	}
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci/* Allocates a new stack in a stack depot pool. */
25962306a36Sopenharmony_cistatic struct stack_record *
26062306a36Sopenharmony_cidepot_alloc_stack(unsigned long *entries, int size, u32 hash, void **prealloc)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	struct stack_record *stack;
26362306a36Sopenharmony_ci	size_t required_size = struct_size(stack, entries, size);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	required_size = ALIGN(required_size, 1 << DEPOT_STACK_ALIGN);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	/* Check if there is not enough space in the current pool. */
26862306a36Sopenharmony_ci	if (unlikely(pool_offset + required_size > DEPOT_POOL_SIZE)) {
26962306a36Sopenharmony_ci		/* Bail out if we reached the pool limit. */
27062306a36Sopenharmony_ci		if (unlikely(pool_index + 1 >= DEPOT_MAX_POOLS)) {
27162306a36Sopenharmony_ci			WARN_ONCE(1, "Stack depot reached limit capacity");
27262306a36Sopenharmony_ci			return NULL;
27362306a36Sopenharmony_ci		}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci		/*
27662306a36Sopenharmony_ci		 * Move on to the next pool.
27762306a36Sopenharmony_ci		 * WRITE_ONCE pairs with potential concurrent read in
27862306a36Sopenharmony_ci		 * stack_depot_fetch().
27962306a36Sopenharmony_ci		 */
28062306a36Sopenharmony_ci		WRITE_ONCE(pool_index, pool_index + 1);
28162306a36Sopenharmony_ci		pool_offset = 0;
28262306a36Sopenharmony_ci		/*
28362306a36Sopenharmony_ci		 * If the maximum number of pools is not reached, take note
28462306a36Sopenharmony_ci		 * that the next pool needs to initialized.
28562306a36Sopenharmony_ci		 * smp_store_release() here pairs with smp_load_acquire() in
28662306a36Sopenharmony_ci		 * stack_depot_save() and depot_init_pool().
28762306a36Sopenharmony_ci		 */
28862306a36Sopenharmony_ci		if (pool_index + 1 < DEPOT_MAX_POOLS)
28962306a36Sopenharmony_ci			smp_store_release(&next_pool_required, 1);
29062306a36Sopenharmony_ci	}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	/* Assign the preallocated memory to a pool if required. */
29362306a36Sopenharmony_ci	if (*prealloc)
29462306a36Sopenharmony_ci		depot_init_pool(prealloc);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	/* Check if we have a pool to save the stack trace. */
29762306a36Sopenharmony_ci	if (stack_pools[pool_index] == NULL)
29862306a36Sopenharmony_ci		return NULL;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	/* Save the stack trace. */
30162306a36Sopenharmony_ci	stack = stack_pools[pool_index] + pool_offset;
30262306a36Sopenharmony_ci	stack->hash = hash;
30362306a36Sopenharmony_ci	stack->size = size;
30462306a36Sopenharmony_ci	stack->handle.pool_index = pool_index;
30562306a36Sopenharmony_ci	stack->handle.offset = pool_offset >> DEPOT_STACK_ALIGN;
30662306a36Sopenharmony_ci	stack->handle.valid = 1;
30762306a36Sopenharmony_ci	stack->handle.extra = 0;
30862306a36Sopenharmony_ci	memcpy(stack->entries, entries, flex_array_size(stack, entries, size));
30962306a36Sopenharmony_ci	pool_offset += required_size;
31062306a36Sopenharmony_ci	/*
31162306a36Sopenharmony_ci	 * Let KMSAN know the stored stack record is initialized. This shall
31262306a36Sopenharmony_ci	 * prevent false positive reports if instrumented code accesses it.
31362306a36Sopenharmony_ci	 */
31462306a36Sopenharmony_ci	kmsan_unpoison_memory(stack, required_size);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	return stack;
31762306a36Sopenharmony_ci}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci/* Calculates the hash for a stack. */
32062306a36Sopenharmony_cistatic inline u32 hash_stack(unsigned long *entries, unsigned int size)
32162306a36Sopenharmony_ci{
32262306a36Sopenharmony_ci	return jhash2((u32 *)entries,
32362306a36Sopenharmony_ci		      array_size(size,  sizeof(*entries)) / sizeof(u32),
32462306a36Sopenharmony_ci		      STACK_HASH_SEED);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci/*
32862306a36Sopenharmony_ci * Non-instrumented version of memcmp().
32962306a36Sopenharmony_ci * Does not check the lexicographical order, only the equality.
33062306a36Sopenharmony_ci */
33162306a36Sopenharmony_cistatic inline
33262306a36Sopenharmony_ciint stackdepot_memcmp(const unsigned long *u1, const unsigned long *u2,
33362306a36Sopenharmony_ci			unsigned int n)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	for ( ; n-- ; u1++, u2++) {
33662306a36Sopenharmony_ci		if (*u1 != *u2)
33762306a36Sopenharmony_ci			return 1;
33862306a36Sopenharmony_ci	}
33962306a36Sopenharmony_ci	return 0;
34062306a36Sopenharmony_ci}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci/* Finds a stack in a bucket of the hash table. */
34362306a36Sopenharmony_cistatic inline struct stack_record *find_stack(struct stack_record *bucket,
34462306a36Sopenharmony_ci					     unsigned long *entries, int size,
34562306a36Sopenharmony_ci					     u32 hash)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	struct stack_record *found;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	for (found = bucket; found; found = found->next) {
35062306a36Sopenharmony_ci		if (found->hash == hash &&
35162306a36Sopenharmony_ci		    found->size == size &&
35262306a36Sopenharmony_ci		    !stackdepot_memcmp(entries, found->entries, size))
35362306a36Sopenharmony_ci			return found;
35462306a36Sopenharmony_ci	}
35562306a36Sopenharmony_ci	return NULL;
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cidepot_stack_handle_t __stack_depot_save(unsigned long *entries,
35962306a36Sopenharmony_ci					unsigned int nr_entries,
36062306a36Sopenharmony_ci					gfp_t alloc_flags, bool can_alloc)
36162306a36Sopenharmony_ci{
36262306a36Sopenharmony_ci	struct stack_record *found = NULL, **bucket;
36362306a36Sopenharmony_ci	union handle_parts retval = { .handle = 0 };
36462306a36Sopenharmony_ci	struct page *page = NULL;
36562306a36Sopenharmony_ci	void *prealloc = NULL;
36662306a36Sopenharmony_ci	unsigned long flags;
36762306a36Sopenharmony_ci	u32 hash;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	/*
37062306a36Sopenharmony_ci	 * If this stack trace is from an interrupt, including anything before
37162306a36Sopenharmony_ci	 * interrupt entry usually leads to unbounded stack depot growth.
37262306a36Sopenharmony_ci	 *
37362306a36Sopenharmony_ci	 * Since use of filter_irq_stacks() is a requirement to ensure stack
37462306a36Sopenharmony_ci	 * depot can efficiently deduplicate interrupt stacks, always
37562306a36Sopenharmony_ci	 * filter_irq_stacks() to simplify all callers' use of stack depot.
37662306a36Sopenharmony_ci	 */
37762306a36Sopenharmony_ci	nr_entries = filter_irq_stacks(entries, nr_entries);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	if (unlikely(nr_entries == 0) || stack_depot_disabled)
38062306a36Sopenharmony_ci		goto fast_exit;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	hash = hash_stack(entries, nr_entries);
38362306a36Sopenharmony_ci	bucket = &stack_table[hash & stack_hash_mask];
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	/*
38662306a36Sopenharmony_ci	 * Fast path: look the stack trace up without locking.
38762306a36Sopenharmony_ci	 * The smp_load_acquire() here pairs with smp_store_release() to
38862306a36Sopenharmony_ci	 * |bucket| below.
38962306a36Sopenharmony_ci	 */
39062306a36Sopenharmony_ci	found = find_stack(smp_load_acquire(bucket), entries, nr_entries, hash);
39162306a36Sopenharmony_ci	if (found)
39262306a36Sopenharmony_ci		goto exit;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/*
39562306a36Sopenharmony_ci	 * Check if another stack pool needs to be initialized. If so, allocate
39662306a36Sopenharmony_ci	 * the memory now - we won't be able to do that under the lock.
39762306a36Sopenharmony_ci	 *
39862306a36Sopenharmony_ci	 * The smp_load_acquire() here pairs with smp_store_release() to
39962306a36Sopenharmony_ci	 * |next_pool_inited| in depot_alloc_stack() and depot_init_pool().
40062306a36Sopenharmony_ci	 */
40162306a36Sopenharmony_ci	if (unlikely(can_alloc && smp_load_acquire(&next_pool_required))) {
40262306a36Sopenharmony_ci		/*
40362306a36Sopenharmony_ci		 * Zero out zone modifiers, as we don't have specific zone
40462306a36Sopenharmony_ci		 * requirements. Keep the flags related to allocation in atomic
40562306a36Sopenharmony_ci		 * contexts and I/O.
40662306a36Sopenharmony_ci		 */
40762306a36Sopenharmony_ci		alloc_flags &= ~GFP_ZONEMASK;
40862306a36Sopenharmony_ci		alloc_flags &= (GFP_ATOMIC | GFP_KERNEL);
40962306a36Sopenharmony_ci		alloc_flags |= __GFP_NOWARN;
41062306a36Sopenharmony_ci		page = alloc_pages(alloc_flags, DEPOT_POOL_ORDER);
41162306a36Sopenharmony_ci		if (page)
41262306a36Sopenharmony_ci			prealloc = page_address(page);
41362306a36Sopenharmony_ci	}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	raw_spin_lock_irqsave(&pool_lock, flags);
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	found = find_stack(*bucket, entries, nr_entries, hash);
41862306a36Sopenharmony_ci	if (!found) {
41962306a36Sopenharmony_ci		struct stack_record *new =
42062306a36Sopenharmony_ci			depot_alloc_stack(entries, nr_entries, hash, &prealloc);
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci		if (new) {
42362306a36Sopenharmony_ci			new->next = *bucket;
42462306a36Sopenharmony_ci			/*
42562306a36Sopenharmony_ci			 * This smp_store_release() pairs with
42662306a36Sopenharmony_ci			 * smp_load_acquire() from |bucket| above.
42762306a36Sopenharmony_ci			 */
42862306a36Sopenharmony_ci			smp_store_release(bucket, new);
42962306a36Sopenharmony_ci			found = new;
43062306a36Sopenharmony_ci		}
43162306a36Sopenharmony_ci	} else if (prealloc) {
43262306a36Sopenharmony_ci		/*
43362306a36Sopenharmony_ci		 * Stack depot already contains this stack trace, but let's
43462306a36Sopenharmony_ci		 * keep the preallocated memory for the future.
43562306a36Sopenharmony_ci		 */
43662306a36Sopenharmony_ci		depot_init_pool(&prealloc);
43762306a36Sopenharmony_ci	}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&pool_lock, flags);
44062306a36Sopenharmony_ciexit:
44162306a36Sopenharmony_ci	if (prealloc) {
44262306a36Sopenharmony_ci		/* Stack depot didn't use this memory, free it. */
44362306a36Sopenharmony_ci		free_pages((unsigned long)prealloc, DEPOT_POOL_ORDER);
44462306a36Sopenharmony_ci	}
44562306a36Sopenharmony_ci	if (found)
44662306a36Sopenharmony_ci		retval.handle = found->handle.handle;
44762306a36Sopenharmony_cifast_exit:
44862306a36Sopenharmony_ci	return retval.handle;
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__stack_depot_save);
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_cidepot_stack_handle_t stack_depot_save(unsigned long *entries,
45362306a36Sopenharmony_ci				      unsigned int nr_entries,
45462306a36Sopenharmony_ci				      gfp_t alloc_flags)
45562306a36Sopenharmony_ci{
45662306a36Sopenharmony_ci	return __stack_depot_save(entries, nr_entries, alloc_flags, true);
45762306a36Sopenharmony_ci}
45862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stack_depot_save);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ciunsigned int stack_depot_fetch(depot_stack_handle_t handle,
46162306a36Sopenharmony_ci			       unsigned long **entries)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	union handle_parts parts = { .handle = handle };
46462306a36Sopenharmony_ci	/*
46562306a36Sopenharmony_ci	 * READ_ONCE pairs with potential concurrent write in
46662306a36Sopenharmony_ci	 * depot_alloc_stack.
46762306a36Sopenharmony_ci	 */
46862306a36Sopenharmony_ci	int pool_index_cached = READ_ONCE(pool_index);
46962306a36Sopenharmony_ci	void *pool;
47062306a36Sopenharmony_ci	size_t offset = parts.offset << DEPOT_STACK_ALIGN;
47162306a36Sopenharmony_ci	struct stack_record *stack;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	*entries = NULL;
47462306a36Sopenharmony_ci	/*
47562306a36Sopenharmony_ci	 * Let KMSAN know *entries is initialized. This shall prevent false
47662306a36Sopenharmony_ci	 * positive reports if instrumented code accesses it.
47762306a36Sopenharmony_ci	 */
47862306a36Sopenharmony_ci	kmsan_unpoison_memory(entries, sizeof(*entries));
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	if (!handle)
48162306a36Sopenharmony_ci		return 0;
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	if (parts.pool_index > pool_index_cached) {
48462306a36Sopenharmony_ci		WARN(1, "pool index %d out of bounds (%d) for stack id %08x\n",
48562306a36Sopenharmony_ci			parts.pool_index, pool_index_cached, handle);
48662306a36Sopenharmony_ci		return 0;
48762306a36Sopenharmony_ci	}
48862306a36Sopenharmony_ci	pool = stack_pools[parts.pool_index];
48962306a36Sopenharmony_ci	if (!pool)
49062306a36Sopenharmony_ci		return 0;
49162306a36Sopenharmony_ci	stack = pool + offset;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	*entries = stack->entries;
49462306a36Sopenharmony_ci	return stack->size;
49562306a36Sopenharmony_ci}
49662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stack_depot_fetch);
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_civoid stack_depot_print(depot_stack_handle_t stack)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	unsigned long *entries;
50162306a36Sopenharmony_ci	unsigned int nr_entries;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	nr_entries = stack_depot_fetch(stack, &entries);
50462306a36Sopenharmony_ci	if (nr_entries > 0)
50562306a36Sopenharmony_ci		stack_trace_print(entries, nr_entries, 0);
50662306a36Sopenharmony_ci}
50762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stack_depot_print);
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ciint stack_depot_snprint(depot_stack_handle_t handle, char *buf, size_t size,
51062306a36Sopenharmony_ci		       int spaces)
51162306a36Sopenharmony_ci{
51262306a36Sopenharmony_ci	unsigned long *entries;
51362306a36Sopenharmony_ci	unsigned int nr_entries;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	nr_entries = stack_depot_fetch(handle, &entries);
51662306a36Sopenharmony_ci	return nr_entries ? stack_trace_snprint(buf, size, entries, nr_entries,
51762306a36Sopenharmony_ci						spaces) : 0;
51862306a36Sopenharmony_ci}
51962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(stack_depot_snprint);
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_cidepot_stack_handle_t __must_check stack_depot_set_extra_bits(
52262306a36Sopenharmony_ci			depot_stack_handle_t handle, unsigned int extra_bits)
52362306a36Sopenharmony_ci{
52462306a36Sopenharmony_ci	union handle_parts parts = { .handle = handle };
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	/* Don't set extra bits on empty handles. */
52762306a36Sopenharmony_ci	if (!handle)
52862306a36Sopenharmony_ci		return 0;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	parts.extra = extra_bits;
53162306a36Sopenharmony_ci	return parts.handle;
53262306a36Sopenharmony_ci}
53362306a36Sopenharmony_ciEXPORT_SYMBOL(stack_depot_set_extra_bits);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ciunsigned int stack_depot_get_extra_bits(depot_stack_handle_t handle)
53662306a36Sopenharmony_ci{
53762306a36Sopenharmony_ci	union handle_parts parts = { .handle = handle };
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	return parts.extra;
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ciEXPORT_SYMBOL(stack_depot_get_extra_bits);
542