Tracing's transition recursion slot exists because a callback can run after
architectural hardirq entry but before generic entry increments
preempt_count(). Steve asked whether the count could be updated soon enough
to remove that slot. This RFC establishes that entry contract on arm64 and
closes a separate recursion window exposed by the same tests.
This is a design RFC, not a merge-ready proposal. I am looking for
feedback on the entry contract before extending it to other architectures
or removing TRACE_CTX_TRANSITION.
Clang can outline raw preempt-count updates and
__kern_my_cpu_offset() from noinstr entry code. This series applies to a
tree with the following two patches added:
- Hongyan Xia, "arm64: Always inline raw preempt count updates"
https://lore.kernel.org/all/c3a90368dd6c096af9d918e036a27728696fb8a4.1786603168.git.hongyan.xia@transsion.com/ (local)
- Will Deacon, "arm64: percpu: Annotate __kern_my_cpu_offset() as
'__always_inline'"
https://lore.kernel.org/r/20260918161407.2300-12-will@kernel.org (local)
Those patches are external prerequisites and are not included in this
RFC.
Patches 1 through 11 split raw preempt-count updates from generic IRQ
bookkeeping. On arm64, ordinary interrupts add HARDIRQ_OFFSET after the
pseudo-NMI decision but before instrumentable generic entry work. The
remaining accounting still happens in irq_enter_rcu().
The exit side has a similar gap. Function-graph and MTE callbacks can run
after the real hardirq state has been removed, and kernel return may
schedule before them. The series records ordinary-hardirq provenance and
restores a synthetic hardirq classification after the preemption decision.
That tail changes only preempt-count and lockdep state. It does not repeat
interrupt accounting, RCU, or tick entry.
Patch 12 keeps tracing's recursion state inside one preemption-disabled
interval. It closes the transition collision reproduced at the IRQ-exit
reschedule boundary. TRACE_CTX_TRANSITION remains unchanged because
unconverted architecture entry intervals can still run before
preempt_count() reflects hardirq context. An x86-64 no-transition control
still recorded recursion at system-vector entry and exit and in the
deferred hrtimer return tail.
The base includes "entry: Account the deferred hrtimer rearm as hardirq
context for lockdep" and "softirq: Preserve interrupt context on return
from interrupt".
The main questions are:
- Should generic entry expose separate raw-update and bookkeeping phases?
- Are preempt count and lockdep state sufficient for the return tail?
- Is arm64 a suitable first user of this contract?
- Should the recursion-lifetime fix travel with the entry conversion?
Karl Mehltretter (12):
sched: Split preempt-count bookkeeping from raw updates
lockdep: Use raw access for pinned hardirq state
entry: Add the pre-counted ordinary-hardirq entry/exit contract
entry: Skip inactive IRQ-return reschedule calls
context_tracking: Split IRQ-exit preparation from the EQS transition
lockdep: Prepare IRQ-on state from a hardirq return tail
entry: Carry ordinary-hardirq provenance through kernel return
entry: Classify ordinary hardirq return-tail work as hardirq context
arm64: Use the pre-counted hardirq lifecycle
docs: entry: Describe the pre-counted hardirq lifecycle
locking/selftest: Exercise hardirq return-tail preparation
tracing: Pin recursion state for its complete lifetime
Documentation/core-api/entry.rst | 75 ++++++++++--
arch/arm64/include/asm/preempt.h | 2 +-
arch/arm64/kernel/entry-common.c | 25 ++--
include/linux/context_tracking_irq.h | 32 +++++-
include/linux/hardirq.h | 29 +++++
include/linux/interrupt.h | 2 +-
include/linux/irq-entry-common.h | 96 ++++++++++++++--
include/linux/irqflags.h | 14 ++-
include/linux/preempt.h | 9 ++
include/linux/trace_recursion.h | 14 ++-
kernel/context_tracking.c | 78 ++++++++++---
kernel/entry/common.c | 38 +++++-
kernel/locking/lockdep.c | 48 +++++---
kernel/sched/core.c | 68 +++++++++--
kernel/softirq.c | 166 +++++++++++++++++++++++----
lib/locking-selftest.c | 53 +++++++++
16 files changed, 648 insertions(+), 101 deletions(-)
base-commit: 779ab5d73a22c798d1273b4aaf50cf5b8d750be9
prerequisite-patch-id: 9c009809614854fbff979d65aad6732757d006d5
prerequisite-patch-id: 764fd197db36a3889548bbc41890dd5b3d902f99
--
2.39.5 (Apple Git-154)