Skip to content

Commit 0923fd0

Browse files
committed
Merge tag 'locking-core-2026-02-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking updates from Ingo Molnar: "Lock debugging: - Implement compiler-driven static analysis locking context checking, using the upcoming Clang 22 compiler's context analysis features (Marco Elver) We removed Sparse context analysis support, because prior to removal even a defconfig kernel produced 1,700+ context tracking Sparse warnings, the overwhelming majority of which are false positives. On an allmodconfig kernel the number of false positive context tracking Sparse warnings grows to over 5,200... On the plus side of the balance actual locking bugs found by Sparse context analysis is also rather ... sparse: I found only 3 such commits in the last 3 years. So the rate of false positives and the maintenance overhead is rather high and there appears to be no active policy in place to achieve a zero-warnings baseline to move the annotations & fixers to developers who introduce new code. Clang context analysis is more complete and more aggressive in trying to find bugs, at least in principle. Plus it has a different model to enabling it: it's enabled subsystem by subsystem, which results in zero warnings on all relevant kernel builds (as far as our testing managed to cover it). Which allowed us to enable it by default, similar to other compiler warnings, with the expectation that there are no warnings going forward. This enforces a zero-warnings baseline on clang-22+ builds (Which are still limited in distribution, admittedly) Hopefully the Clang approach can lead to a more maintainable zero-warnings status quo and policy, with more and more subsystems and drivers enabling the feature. Context tracking can be enabled for all kernel code via WARN_CONTEXT_ANALYSIS_ALL=y (default disabled), but this will generate a lot of false positives. ( Having said that, Sparse support could still be added back, if anyone is interested - the removal patch is still relatively straightforward to revert at this stage. ) Rust integration updates: (Alice Ryhl, Fujita Tomonori, Boqun Feng) - Add support for Atomic<i8/i16/bool> and replace most Rust native AtomicBool usages with Atomic<bool> - Clean up LockClassKey and improve its documentation - Add missing Send and Sync trait implementation for SetOnce - Make ARef Unpin as it is supposed to be - Add __rust_helper to a few Rust helpers as a preparation for helper LTO - Inline various lock related functions to avoid additional function calls WW mutexes: - Extend ww_mutex tests and other test-ww_mutex updates (John Stultz) Misc fixes and cleanups: - rcu: Mark lockdep_assert_rcu_helper() __always_inline (Arnd Bergmann) - locking/local_lock: Include more missing headers (Peter Zijlstra) - seqlock: fix scoped_seqlock_read kernel-doc (Randy Dunlap) - rust: sync: Replace `kernel::c_str!` with C-Strings (Tamir Duberstein)" * tag 'locking-core-2026-02-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (90 commits) locking/rwlock: Fix write_trylock_irqsave() with CONFIG_INLINE_WRITE_TRYLOCK rcu: Mark lockdep_assert_rcu_helper() __always_inline compiler-context-analysis: Remove __assume_ctx_lock from initializers tomoyo: Use scoped init guard crypto: Use scoped init guard kcov: Use scoped init guard compiler-context-analysis: Introduce scoped init guards cleanup: Make __DEFINE_LOCK_GUARD handle commas in initializers seqlock: fix scoped_seqlock_read kernel-doc tools: Update context analysis macros in compiler_types.h rust: sync: Replace `kernel::c_str!` with C-Strings rust: sync: Inline various lock related methods rust: helpers: Move #define __rust_helper out of atomic.c rust: wait: Add __rust_helper to helpers rust: time: Add __rust_helper to helpers rust: task: Add __rust_helper to helpers rust: sync: Add __rust_helper to helpers rust: refcount: Add __rust_helper to helpers rust: rcu: Add __rust_helper to helpers rust: processor: Add __rust_helper to helpers ...
2 parents 4d84667 + 7a562d5 commit 0923fd0

144 files changed

Lines changed: 3222 additions & 861 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
.. Copyright (C) 2025, Google LLC.
3+
4+
.. _context-analysis:
5+
6+
Compiler-Based Context Analysis
7+
===============================
8+
9+
Context Analysis is a language extension, which enables statically checking
10+
that required contexts are active (or inactive) by acquiring and releasing
11+
user-definable "context locks". An obvious application is lock-safety checking
12+
for the kernel's various synchronization primitives (each of which represents a
13+
"context lock"), and checking that locking rules are not violated.
14+
15+
The Clang compiler currently supports the full set of context analysis
16+
features. To enable for Clang, configure the kernel with::
17+
18+
CONFIG_WARN_CONTEXT_ANALYSIS=y
19+
20+
The feature requires Clang 22 or later.
21+
22+
The analysis is *opt-in by default*, and requires declaring which modules and
23+
subsystems should be analyzed in the respective `Makefile`::
24+
25+
CONTEXT_ANALYSIS_mymodule.o := y
26+
27+
Or for all translation units in the directory::
28+
29+
CONTEXT_ANALYSIS := y
30+
31+
It is possible to enable the analysis tree-wide, however, which will result in
32+
numerous false positive warnings currently and is *not* generally recommended::
33+
34+
CONFIG_WARN_CONTEXT_ANALYSIS_ALL=y
35+
36+
Programming Model
37+
-----------------
38+
39+
The below describes the programming model around using context lock types.
40+
41+
.. note::
42+
Enabling context analysis can be seen as enabling a dialect of Linux C with
43+
a Context System. Some valid patterns involving complex control-flow are
44+
constrained (such as conditional acquisition and later conditional release
45+
in the same function).
46+
47+
Context analysis is a way to specify permissibility of operations to depend on
48+
context locks being held (or not held). Typically we are interested in
49+
protecting data and code in a critical section by requiring a specific context
50+
to be active, for example by holding a specific lock. The analysis ensures that
51+
callers cannot perform an operation without the required context being active.
52+
53+
Context locks are associated with named structs, along with functions that
54+
operate on struct instances to acquire and release the associated context lock.
55+
56+
Context locks can be held either exclusively or shared. This mechanism allows
57+
assigning more precise privileges when a context is active, typically to
58+
distinguish where a thread may only read (shared) or also write (exclusive) to
59+
data guarded within a context.
60+
61+
The set of contexts that are actually active in a given thread at a given point
62+
in program execution is a run-time concept. The static analysis works by
63+
calculating an approximation of that set, called the context environment. The
64+
context environment is calculated for every program point, and describes the
65+
set of contexts that are statically known to be active, or inactive, at that
66+
particular point. This environment is a conservative approximation of the full
67+
set of contexts that will actually be active in a thread at run-time.
68+
69+
More details are also documented `here
70+
<https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_.
71+
72+
.. note::
73+
Clang's analysis explicitly does not infer context locks acquired or
74+
released by inline functions. It requires explicit annotations to (a) assert
75+
that it's not a bug if a context lock is released or acquired, and (b) to
76+
retain consistency between inline and non-inline function declarations.
77+
78+
Supported Kernel Primitives
79+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
80+
81+
Currently the following synchronization primitives are supported:
82+
`raw_spinlock_t`, `spinlock_t`, `rwlock_t`, `mutex`, `seqlock_t`,
83+
`bit_spinlock`, RCU, SRCU (`srcu_struct`), `rw_semaphore`, `local_lock_t`,
84+
`ww_mutex`.
85+
86+
To initialize variables guarded by a context lock with an initialization
87+
function (``type_init(&lock)``), prefer using ``guard(type_init)(&lock)`` or
88+
``scoped_guard(type_init, &lock) { ... }`` to initialize such guarded members
89+
or globals in the enclosing scope. This initializes the context lock and treats
90+
the context as active within the initialization scope (initialization implies
91+
exclusive access to the underlying object).
92+
93+
For example::
94+
95+
struct my_data {
96+
spinlock_t lock;
97+
int counter __guarded_by(&lock);
98+
};
99+
100+
void init_my_data(struct my_data *d)
101+
{
102+
...
103+
guard(spinlock_init)(&d->lock);
104+
d->counter = 0;
105+
...
106+
}
107+
108+
Alternatively, initializing guarded variables can be done with context analysis
109+
disabled, preferably in the smallest possible scope (due to lack of any other
110+
checking): either with a ``context_unsafe(var = init)`` expression, or by
111+
marking small initialization functions with the ``__context_unsafe(init)``
112+
attribute.
113+
114+
Lockdep assertions, such as `lockdep_assert_held()`, inform the compiler's
115+
context analysis that the associated synchronization primitive is held after
116+
the assertion. This avoids false positives in complex control-flow scenarios
117+
and encourages the use of Lockdep where static analysis is limited. For
118+
example, this is useful when a function doesn't *always* require a lock, making
119+
`__must_hold()` inappropriate.
120+
121+
Keywords
122+
~~~~~~~~
123+
124+
.. kernel-doc:: include/linux/compiler-context-analysis.h
125+
:identifiers: context_lock_struct
126+
token_context_lock token_context_lock_instance
127+
__guarded_by __pt_guarded_by
128+
__must_hold
129+
__must_not_hold
130+
__acquires
131+
__cond_acquires
132+
__releases
133+
__must_hold_shared
134+
__acquires_shared
135+
__cond_acquires_shared
136+
__releases_shared
137+
__acquire
138+
__release
139+
__acquire_shared
140+
__release_shared
141+
__acquire_ret
142+
__acquire_shared_ret
143+
context_unsafe
144+
__context_unsafe
145+
disable_context_analysis enable_context_analysis
146+
147+
.. note::
148+
The function attribute `__no_context_analysis` is reserved for internal
149+
implementation of context lock types, and should be avoided in normal code.
150+
151+
Background
152+
----------
153+
154+
Clang originally called the feature `Thread Safety Analysis
155+
<https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_, with some keywords
156+
and documentation still using the thread-safety-analysis-only terminology. This
157+
was later changed and the feature became more flexible, gaining the ability to
158+
define custom "capabilities". Its foundations can be found in `Capability
159+
Systems <https://www.cs.cornell.edu/talc/papers/capabilities.pdf>`_, used to
160+
specify the permissibility of operations to depend on some "capability" being
161+
held (or not held).
162+
163+
Because the feature is not just able to express capabilities related to
164+
synchronization primitives, and "capability" is already overloaded in the
165+
kernel, the naming chosen for the kernel departs from Clang's initial "Thread
166+
Safety" and "capability" nomenclature; we refer to the feature as "Context
167+
Analysis" to avoid confusion. The internal implementation still makes
168+
references to Clang's terminology in a few places, such as `-Wthread-safety`
169+
being the warning option that also still appears in diagnostic messages.

Documentation/dev-tools/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Documentation/process/debugging/index.rst
2121
checkpatch
2222
clang-format
2323
coccinelle
24+
context-analysis
2425
sparse
2526
kcov
2627
gcov

Documentation/dev-tools/sparse.rst

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,6 @@ sure that bitwise types don't get mixed up (little-endian vs big-endian
5353
vs cpu-endian vs whatever), and there the constant "0" really _is_
5454
special.
5555

56-
Using sparse for lock checking
57-
------------------------------
58-
59-
The following macros are undefined for gcc and defined during a sparse
60-
run to use the "context" tracking feature of sparse, applied to
61-
locking. These annotations tell sparse when a lock is held, with
62-
regard to the annotated function's entry and exit.
63-
64-
__must_hold - The specified lock is held on function entry and exit.
65-
66-
__acquires - The specified lock is held on function exit, but not entry.
67-
68-
__releases - The specified lock is held on function entry, but not exit.
69-
70-
If the function enters and exits without the lock held, acquiring and
71-
releasing the lock inside the function in a balanced way, no
72-
annotation is needed. The three annotations above are for cases where
73-
sparse would otherwise report a context imbalance.
74-
7556
Getting sparse
7657
--------------
7758

Documentation/mm/process_addrs.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ To access PTE-level page tables, a helper like :c:func:`!pte_offset_map_lock` or
583583
:c:func:`!pte_offset_map` can be used depending on stability requirements.
584584
These map the page table into kernel memory if required, take the RCU lock, and
585585
depending on variant, may also look up or acquire the PTE lock.
586-
See the comment on :c:func:`!__pte_offset_map_lock`.
586+
See the comment on :c:func:`!pte_offset_map_lock`.
587587

588588
Atomicity
589589
^^^^^^^^^
@@ -667,7 +667,7 @@ must be released via :c:func:`!pte_unmap_unlock`.
667667
.. note:: There are some variants on this, such as
668668
:c:func:`!pte_offset_map_rw_nolock` when we know we hold the PTE stable but
669669
for brevity we do not explore this. See the comment for
670-
:c:func:`!__pte_offset_map_lock` for more details.
670+
:c:func:`!pte_offset_map_lock` for more details.
671671

672672
When modifying data in ranges we typically only wish to allocate higher page
673673
tables as necessary, using these locks to avoid races or overwriting anything,
@@ -686,7 +686,7 @@ At the leaf page table, that is the PTE, we can't entirely rely on this pattern
686686
as we have separate PMD and PTE locks and a THP collapse for instance might have
687687
eliminated the PMD entry as well as the PTE from under us.
688688

689-
This is why :c:func:`!__pte_offset_map_lock` locklessly retrieves the PMD entry
689+
This is why :c:func:`!pte_offset_map_lock` locklessly retrieves the PMD entry
690690
for the PTE, carefully checking it is as expected, before acquiring the
691691
PTE-specific lock, and then *again* checking that the PMD entry is as expected.
692692

MAINTAINERS

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6153,6 +6153,17 @@ M: Nelson Escobar <neescoba@cisco.com>
61536153
S: Supported
61546154
F: drivers/infiniband/hw/usnic/
61556155

6156+
CLANG CONTEXT ANALYSIS
6157+
M: Marco Elver <elver@google.com>
6158+
R: Bart Van Assche <bvanassche@acm.org>
6159+
L: llvm@lists.linux.dev
6160+
S: Maintained
6161+
F: Documentation/dev-tools/context-analysis.rst
6162+
F: include/linux/compiler-context-analysis.h
6163+
F: lib/test_context-analysis.c
6164+
F: scripts/Makefile.context-analysis
6165+
F: scripts/context-analysis-suppression.txt
6166+
61566167
CLANG CONTROL FLOW INTEGRITY SUPPORT
61576168
M: Sami Tolvanen <samitolvanen@google.com>
61586169
M: Kees Cook <kees@kernel.org>

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,7 @@ include-$(CONFIG_RANDSTRUCT) += scripts/Makefile.randstruct
11251125
include-$(CONFIG_KSTACK_ERASE) += scripts/Makefile.kstack_erase
11261126
include-$(CONFIG_AUTOFDO_CLANG) += scripts/Makefile.autofdo
11271127
include-$(CONFIG_PROPELLER_CLANG) += scripts/Makefile.propeller
1128+
include-$(CONFIG_WARN_CONTEXT_ANALYSIS) += scripts/Makefile.context-analysis
11281129
include-$(CONFIG_GCC_PLUGINS) += scripts/Makefile.gcc-plugins
11291130

11301131
include $(addprefix $(srctree)/, $(include-y))

arch/um/include/shared/skas/mm_id.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ struct mm_id {
2121
int syscall_fd_map[STUB_MAX_FDS];
2222
};
2323

24-
void enter_turnstile(struct mm_id *mm_id) __acquires(turnstile);
25-
void exit_turnstile(struct mm_id *mm_id) __releases(turnstile);
24+
struct mutex *__get_turnstile(struct mm_id *mm_id);
25+
void enter_turnstile(struct mm_id *mm_id) __acquires(__get_turnstile(mm_id));
26+
void exit_turnstile(struct mm_id *mm_id) __releases(__get_turnstile(mm_id));
2627

2728
void notify_mm_kill(int pid);
2829

arch/um/kernel/skas/mmu.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,21 @@ static_assert(sizeof(struct stub_data) == STUB_DATA_PAGES * UM_KERN_PAGE_SIZE);
2323
static spinlock_t mm_list_lock;
2424
static struct list_head mm_list;
2525

26-
void enter_turnstile(struct mm_id *mm_id) __acquires(turnstile)
26+
struct mutex *__get_turnstile(struct mm_id *mm_id)
2727
{
2828
struct mm_context *ctx = container_of(mm_id, struct mm_context, id);
2929

30-
mutex_lock(&ctx->turnstile);
30+
return &ctx->turnstile;
3131
}
3232

33-
void exit_turnstile(struct mm_id *mm_id) __releases(turnstile)
33+
void enter_turnstile(struct mm_id *mm_id)
3434
{
35-
struct mm_context *ctx = container_of(mm_id, struct mm_context, id);
35+
mutex_lock(__get_turnstile(mm_id));
36+
}
3637

37-
mutex_unlock(&ctx->turnstile);
38+
void exit_turnstile(struct mm_id *mm_id)
39+
{
40+
mutex_unlock(__get_turnstile(mm_id));
3841
}
3942

4043
int init_new_context(struct task_struct *task, struct mm_struct *mm)

arch/x86/um/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ endmenu
99
config UML_X86
1010
def_bool y
1111
select ARCH_USE_QUEUED_RWLOCKS
12+
select ARCH_SUPPORTS_ATOMIC_RMW
1213
select ARCH_USE_QUEUED_SPINLOCKS
1314
select DCACHE_WORD_ACCESS
1415
select HAVE_EFFICIENT_UNALIGNED_ACCESS

crypto/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# Cryptographic API
44
#
55

6+
CONTEXT_ANALYSIS := y
7+
68
obj-$(CONFIG_CRYPTO) += crypto.o
79
crypto-y := api.o cipher.o
810

0 commit comments

Comments
 (0)