162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * kernel/lockdep_internals.h 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Runtime locking correctness validator 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * lockdep subsystem internal functions and variables. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* 1162306a36Sopenharmony_ci * Lock-class usage-state bits: 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_cienum lock_usage_bit { 1462306a36Sopenharmony_ci#define LOCKDEP_STATE(__STATE) \ 1562306a36Sopenharmony_ci LOCK_USED_IN_##__STATE, \ 1662306a36Sopenharmony_ci LOCK_USED_IN_##__STATE##_READ, \ 1762306a36Sopenharmony_ci LOCK_ENABLED_##__STATE, \ 1862306a36Sopenharmony_ci LOCK_ENABLED_##__STATE##_READ, 1962306a36Sopenharmony_ci#include "lockdep_states.h" 2062306a36Sopenharmony_ci#undef LOCKDEP_STATE 2162306a36Sopenharmony_ci LOCK_USED, 2262306a36Sopenharmony_ci LOCK_USED_READ, 2362306a36Sopenharmony_ci LOCK_USAGE_STATES, 2462306a36Sopenharmony_ci}; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci/* states after LOCK_USED_READ are not traced and printed */ 2762306a36Sopenharmony_cistatic_assert(LOCK_TRACE_STATES == LOCK_USAGE_STATES); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define LOCK_USAGE_READ_MASK 1 3062306a36Sopenharmony_ci#define LOCK_USAGE_DIR_MASK 2 3162306a36Sopenharmony_ci#define LOCK_USAGE_STATE_MASK (~(LOCK_USAGE_READ_MASK | LOCK_USAGE_DIR_MASK)) 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* 3462306a36Sopenharmony_ci * Usage-state bitmasks: 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci#define __LOCKF(__STATE) LOCKF_##__STATE = (1 << LOCK_##__STATE), 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cienum { 3962306a36Sopenharmony_ci#define LOCKDEP_STATE(__STATE) \ 4062306a36Sopenharmony_ci __LOCKF(USED_IN_##__STATE) \ 4162306a36Sopenharmony_ci __LOCKF(USED_IN_##__STATE##_READ) \ 4262306a36Sopenharmony_ci __LOCKF(ENABLED_##__STATE) \ 4362306a36Sopenharmony_ci __LOCKF(ENABLED_##__STATE##_READ) 4462306a36Sopenharmony_ci#include "lockdep_states.h" 4562306a36Sopenharmony_ci#undef LOCKDEP_STATE 4662306a36Sopenharmony_ci __LOCKF(USED) 4762306a36Sopenharmony_ci __LOCKF(USED_READ) 4862306a36Sopenharmony_ci}; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define LOCKDEP_STATE(__STATE) LOCKF_ENABLED_##__STATE | 5162306a36Sopenharmony_cistatic const unsigned long LOCKF_ENABLED_IRQ = 5262306a36Sopenharmony_ci#include "lockdep_states.h" 5362306a36Sopenharmony_ci 0; 5462306a36Sopenharmony_ci#undef LOCKDEP_STATE 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define LOCKDEP_STATE(__STATE) LOCKF_USED_IN_##__STATE | 5762306a36Sopenharmony_cistatic const unsigned long LOCKF_USED_IN_IRQ = 5862306a36Sopenharmony_ci#include "lockdep_states.h" 5962306a36Sopenharmony_ci 0; 6062306a36Sopenharmony_ci#undef LOCKDEP_STATE 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define LOCKDEP_STATE(__STATE) LOCKF_ENABLED_##__STATE##_READ | 6362306a36Sopenharmony_cistatic const unsigned long LOCKF_ENABLED_IRQ_READ = 6462306a36Sopenharmony_ci#include "lockdep_states.h" 6562306a36Sopenharmony_ci 0; 6662306a36Sopenharmony_ci#undef LOCKDEP_STATE 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#define LOCKDEP_STATE(__STATE) LOCKF_USED_IN_##__STATE##_READ | 6962306a36Sopenharmony_cistatic const unsigned long LOCKF_USED_IN_IRQ_READ = 7062306a36Sopenharmony_ci#include "lockdep_states.h" 7162306a36Sopenharmony_ci 0; 7262306a36Sopenharmony_ci#undef LOCKDEP_STATE 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define LOCKF_ENABLED_IRQ_ALL (LOCKF_ENABLED_IRQ | LOCKF_ENABLED_IRQ_READ) 7562306a36Sopenharmony_ci#define LOCKF_USED_IN_IRQ_ALL (LOCKF_USED_IN_IRQ | LOCKF_USED_IN_IRQ_READ) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define LOCKF_IRQ (LOCKF_ENABLED_IRQ | LOCKF_USED_IN_IRQ) 7862306a36Sopenharmony_ci#define LOCKF_IRQ_READ (LOCKF_ENABLED_IRQ_READ | LOCKF_USED_IN_IRQ_READ) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/* 8162306a36Sopenharmony_ci * CONFIG_LOCKDEP_SMALL is defined for sparc. Sparc requires .text, 8262306a36Sopenharmony_ci * .data and .bss to fit in required 32MB limit for the kernel. With 8362306a36Sopenharmony_ci * CONFIG_LOCKDEP we could go over this limit and cause system boot-up problems. 8462306a36Sopenharmony_ci * So, reduce the static allocations for lockdeps related structures so that 8562306a36Sopenharmony_ci * everything fits in current required size limit. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci#ifdef CONFIG_LOCKDEP_SMALL 8862306a36Sopenharmony_ci/* 8962306a36Sopenharmony_ci * MAX_LOCKDEP_ENTRIES is the maximum number of lock dependencies 9062306a36Sopenharmony_ci * we track. 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci * We use the per-lock dependency maps in two ways: we grow it by adding 9362306a36Sopenharmony_ci * every to-be-taken lock to all currently held lock's own dependency 9462306a36Sopenharmony_ci * table (if it's not there yet), and we check it for lock order 9562306a36Sopenharmony_ci * conflicts and deadlocks. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_ci#define MAX_LOCKDEP_ENTRIES 16384UL 9862306a36Sopenharmony_ci#define MAX_LOCKDEP_CHAINS_BITS 15 9962306a36Sopenharmony_ci#define MAX_STACK_TRACE_ENTRIES 262144UL 10062306a36Sopenharmony_ci#define STACK_TRACE_HASH_SIZE 8192 10162306a36Sopenharmony_ci#else 10262306a36Sopenharmony_ci#define MAX_LOCKDEP_ENTRIES (1UL << CONFIG_LOCKDEP_BITS) 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci#define MAX_LOCKDEP_CHAINS_BITS CONFIG_LOCKDEP_CHAINS_BITS 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci/* 10762306a36Sopenharmony_ci * Stack-trace: tightly packed array of stack backtrace 10862306a36Sopenharmony_ci * addresses. Protected by the hash_lock. 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_ci#define MAX_STACK_TRACE_ENTRIES (1UL << CONFIG_LOCKDEP_STACK_TRACE_BITS) 11162306a36Sopenharmony_ci#define STACK_TRACE_HASH_SIZE (1 << CONFIG_LOCKDEP_STACK_TRACE_HASH_BITS) 11262306a36Sopenharmony_ci#endif 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/* 11562306a36Sopenharmony_ci * Bit definitions for lock_chain.irq_context 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ci#define LOCK_CHAIN_SOFTIRQ_CONTEXT (1 << 0) 11862306a36Sopenharmony_ci#define LOCK_CHAIN_HARDIRQ_CONTEXT (1 << 1) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS) 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#define MAX_LOCKDEP_CHAIN_HLOCKS (MAX_LOCKDEP_CHAINS*5) 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciextern struct lock_chain lock_chains[]; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci#define LOCK_USAGE_CHARS (2*XXX_LOCK_USAGE_STATES + 1) 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ciextern void get_usage_chars(struct lock_class *class, 12962306a36Sopenharmony_ci char usage[LOCK_USAGE_CHARS]); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ciextern const char *__get_key_name(const struct lockdep_subclass_key *key, 13262306a36Sopenharmony_ci char *str); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistruct lock_class *lock_chain_get_class(struct lock_chain *chain, int i); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ciextern unsigned long nr_lock_classes; 13762306a36Sopenharmony_ciextern unsigned long nr_zapped_classes; 13862306a36Sopenharmony_ciextern unsigned long nr_zapped_lock_chains; 13962306a36Sopenharmony_ciextern unsigned long nr_list_entries; 14062306a36Sopenharmony_cilong lockdep_next_lockchain(long i); 14162306a36Sopenharmony_ciunsigned long lock_chain_count(void); 14262306a36Sopenharmony_ciextern unsigned long nr_stack_trace_entries; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ciextern unsigned int nr_hardirq_chains; 14562306a36Sopenharmony_ciextern unsigned int nr_softirq_chains; 14662306a36Sopenharmony_ciextern unsigned int nr_process_chains; 14762306a36Sopenharmony_ciextern unsigned int nr_free_chain_hlocks; 14862306a36Sopenharmony_ciextern unsigned int nr_lost_chain_hlocks; 14962306a36Sopenharmony_ciextern unsigned int nr_large_chain_blocks; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciextern unsigned int max_lockdep_depth; 15262306a36Sopenharmony_ciextern unsigned int max_bfs_queue_depth; 15362306a36Sopenharmony_ciextern unsigned long max_lock_class_idx; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ciextern struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; 15662306a36Sopenharmony_ciextern unsigned long lock_classes_in_use[]; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci#ifdef CONFIG_PROVE_LOCKING 15962306a36Sopenharmony_ciextern unsigned long lockdep_count_forward_deps(struct lock_class *); 16062306a36Sopenharmony_ciextern unsigned long lockdep_count_backward_deps(struct lock_class *); 16162306a36Sopenharmony_ci#ifdef CONFIG_TRACE_IRQFLAGS 16262306a36Sopenharmony_ciu64 lockdep_stack_trace_count(void); 16362306a36Sopenharmony_ciu64 lockdep_stack_hash_count(void); 16462306a36Sopenharmony_ci#endif 16562306a36Sopenharmony_ci#else 16662306a36Sopenharmony_cistatic inline unsigned long 16762306a36Sopenharmony_cilockdep_count_forward_deps(struct lock_class *class) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci return 0; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_cistatic inline unsigned long 17262306a36Sopenharmony_cilockdep_count_backward_deps(struct lock_class *class) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci return 0; 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci#endif 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_LOCKDEP 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci#include <asm/local.h> 18162306a36Sopenharmony_ci/* 18262306a36Sopenharmony_ci * Various lockdep statistics. 18362306a36Sopenharmony_ci * We want them per cpu as they are often accessed in fast path 18462306a36Sopenharmony_ci * and we want to avoid too much cache bouncing. 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_cistruct lockdep_stats { 18762306a36Sopenharmony_ci unsigned long chain_lookup_hits; 18862306a36Sopenharmony_ci unsigned int chain_lookup_misses; 18962306a36Sopenharmony_ci unsigned long hardirqs_on_events; 19062306a36Sopenharmony_ci unsigned long hardirqs_off_events; 19162306a36Sopenharmony_ci unsigned long redundant_hardirqs_on; 19262306a36Sopenharmony_ci unsigned long redundant_hardirqs_off; 19362306a36Sopenharmony_ci unsigned long softirqs_on_events; 19462306a36Sopenharmony_ci unsigned long softirqs_off_events; 19562306a36Sopenharmony_ci unsigned long redundant_softirqs_on; 19662306a36Sopenharmony_ci unsigned long redundant_softirqs_off; 19762306a36Sopenharmony_ci int nr_unused_locks; 19862306a36Sopenharmony_ci unsigned int nr_redundant_checks; 19962306a36Sopenharmony_ci unsigned int nr_redundant; 20062306a36Sopenharmony_ci unsigned int nr_cyclic_checks; 20162306a36Sopenharmony_ci unsigned int nr_find_usage_forwards_checks; 20262306a36Sopenharmony_ci unsigned int nr_find_usage_backwards_checks; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* 20562306a36Sopenharmony_ci * Per lock class locking operation stat counts 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_ci unsigned long lock_class_ops[MAX_LOCKDEP_KEYS]; 20862306a36Sopenharmony_ci}; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ciDECLARE_PER_CPU(struct lockdep_stats, lockdep_stats); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci#define __debug_atomic_inc(ptr) \ 21362306a36Sopenharmony_ci this_cpu_inc(lockdep_stats.ptr); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci#define debug_atomic_inc(ptr) { \ 21662306a36Sopenharmony_ci WARN_ON_ONCE(!irqs_disabled()); \ 21762306a36Sopenharmony_ci __this_cpu_inc(lockdep_stats.ptr); \ 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci#define debug_atomic_dec(ptr) { \ 22162306a36Sopenharmony_ci WARN_ON_ONCE(!irqs_disabled()); \ 22262306a36Sopenharmony_ci __this_cpu_dec(lockdep_stats.ptr); \ 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci#define debug_atomic_read(ptr) ({ \ 22662306a36Sopenharmony_ci struct lockdep_stats *__cpu_lockdep_stats; \ 22762306a36Sopenharmony_ci unsigned long long __total = 0; \ 22862306a36Sopenharmony_ci int __cpu; \ 22962306a36Sopenharmony_ci for_each_possible_cpu(__cpu) { \ 23062306a36Sopenharmony_ci __cpu_lockdep_stats = &per_cpu(lockdep_stats, __cpu); \ 23162306a36Sopenharmony_ci __total += __cpu_lockdep_stats->ptr; \ 23262306a36Sopenharmony_ci } \ 23362306a36Sopenharmony_ci __total; \ 23462306a36Sopenharmony_ci}) 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic inline void debug_class_ops_inc(struct lock_class *class) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci int idx; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci idx = class - lock_classes; 24162306a36Sopenharmony_ci __debug_atomic_inc(lock_class_ops[idx]); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic inline unsigned long debug_class_ops_read(struct lock_class *class) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci int idx, cpu; 24762306a36Sopenharmony_ci unsigned long ops = 0; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci idx = class - lock_classes; 25062306a36Sopenharmony_ci for_each_possible_cpu(cpu) 25162306a36Sopenharmony_ci ops += per_cpu(lockdep_stats.lock_class_ops[idx], cpu); 25262306a36Sopenharmony_ci return ops; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci#else 25662306a36Sopenharmony_ci# define __debug_atomic_inc(ptr) do { } while (0) 25762306a36Sopenharmony_ci# define debug_atomic_inc(ptr) do { } while (0) 25862306a36Sopenharmony_ci# define debug_atomic_dec(ptr) do { } while (0) 25962306a36Sopenharmony_ci# define debug_atomic_read(ptr) 0 26062306a36Sopenharmony_ci# define debug_class_ops_inc(ptr) do { } while (0) 26162306a36Sopenharmony_ci#endif 262