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