* [PATCH v9 5/6] x86/vdso: Use CFI macros in __vdso_sgx_enter_enclave()
From: Jens Remus @ 2026-02-11 14:13 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
Steven Rostedt
Cc: Jens Remus, Josh Poimboeuf, Masami Hiramatsu, Mathieu Desnoyers,
Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
H. Peter Anvin, Liam R. Howlett, Lorenzo Stoakes, Michal Hocko,
Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
Heiko Carstens, Vasily Gorbik, Steven Rostedt (Google)
In-Reply-To: <20260211141357.271402-1-jremus@linux.ibm.com>
From: Josh Poimboeuf <jpoimboe@kernel.org>
Use the CFI macros instead of the raw .cfi_* directives to be consistent
with the rest of the VDSO asm. It's also easier on the eyes.
No functional changes.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Acked-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
arch/x86/entry/vdso/vdso64/vsgx.S | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/arch/x86/entry/vdso/vdso64/vsgx.S b/arch/x86/entry/vdso/vdso64/vsgx.S
index c0342238c976..76efbeb1e287 100644
--- a/arch/x86/entry/vdso/vdso64/vsgx.S
+++ b/arch/x86/entry/vdso/vdso64/vsgx.S
@@ -25,12 +25,12 @@
SYM_FUNC_START(__vdso_sgx_enter_enclave)
push %rbp
- .cfi_adjust_cfa_offset 8
- .cfi_rel_offset %rbp, 0
+ CFI_ADJUST_CFA_OFFSET 8
+ CFI_REL_OFFSET %rbp, 0
mov %rsp, %rbp
- .cfi_def_cfa_register %rbp
+ CFI_DEF_CFA_REGISTER %rbp
push %rbx
- .cfi_rel_offset %rbx, -8
+ CFI_REL_OFFSET %rbx, -8
mov %ecx, %eax
.Lenter_enclave:
@@ -77,13 +77,11 @@ SYM_FUNC_START(__vdso_sgx_enter_enclave)
.Lout:
pop %rbx
leave
- .cfi_def_cfa %rsp, 8
+ CFI_DEF_CFA %rsp, 8
RET
- /* The out-of-line code runs with the pre-leave stack frame. */
- .cfi_def_cfa %rbp, 16
-
.Linvalid_input:
+ CFI_DEF_CFA %rbp, 16
mov $(-EINVAL), %eax
jmp .Lout
--
2.51.0
^ permalink raw reply related
* [PATCH v9 4/6] x86/vdso: Use SYM_FUNC_{START,END} in __kernel_vsyscall()
From: Jens Remus @ 2026-02-11 14:13 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
Steven Rostedt
Cc: Jens Remus, Josh Poimboeuf, Masami Hiramatsu, Mathieu Desnoyers,
Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
H. Peter Anvin, Liam R. Howlett, Lorenzo Stoakes, Michal Hocko,
Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
Heiko Carstens, Vasily Gorbik, Steven Rostedt (Google)
In-Reply-To: <20260211141357.271402-1-jremus@linux.ibm.com>
From: Josh Poimboeuf <jpoimboe@kernel.org>
Use SYM_FUNC_{START,END} instead of all the boilerplate. No functional
change.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Acked-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
arch/x86/entry/vdso/vdso32/system_call.S | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/arch/x86/entry/vdso/vdso32/system_call.S b/arch/x86/entry/vdso/vdso32/system_call.S
index 9157cf9c5749..a90f4f7de396 100644
--- a/arch/x86/entry/vdso/vdso32/system_call.S
+++ b/arch/x86/entry/vdso/vdso32/system_call.S
@@ -9,11 +9,7 @@
#include <asm/alternative.h>
.text
- .globl __kernel_vsyscall
- .type __kernel_vsyscall,@function
- ALIGN
-__kernel_vsyscall:
- CFI_STARTPROC
+SYM_FUNC_START(__kernel_vsyscall)
/*
* If using int $0x80, there is no reason to muck about with the
@@ -85,7 +81,5 @@ SYM_INNER_LABEL(int80_landing_pad, SYM_L_GLOBAL)
CFI_RESTORE ecx
CFI_ADJUST_CFA_OFFSET -4
RET
- CFI_ENDPROC
-
- .size __kernel_vsyscall,.-__kernel_vsyscall
+SYM_FUNC_END(__kernel_vsyscall)
.previous
--
2.51.0
^ permalink raw reply related
* [PATCH v9 1/6] x86/vdso: Fix DWARF generation for getrandom()
From: Jens Remus @ 2026-02-11 14:13 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
Steven Rostedt
Cc: Jens Remus, Josh Poimboeuf, Masami Hiramatsu, Mathieu Desnoyers,
Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
H. Peter Anvin, Liam R. Howlett, Lorenzo Stoakes, Michal Hocko,
Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
Heiko Carstens, Vasily Gorbik, Steven Rostedt (Google)
In-Reply-To: <20260211141357.271402-1-jremus@linux.ibm.com>
From: Josh Poimboeuf <jpoimboe@kernel.org>
Add CFI annotations to the VDSO implementation of getrandom() so it will
have valid DWARF unwinding metadata.
Fixes: 33385150ac45 ("x86: vdso: Wire up getrandom() vDSO implementation")
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Acked-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
arch/x86/entry/vdso/vdso64/vgetrandom-chacha.S | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/x86/entry/vdso/vdso64/vgetrandom-chacha.S b/arch/x86/entry/vdso/vdso64/vgetrandom-chacha.S
index bcba5639b8ee..cc82da9216fb 100644
--- a/arch/x86/entry/vdso/vdso64/vgetrandom-chacha.S
+++ b/arch/x86/entry/vdso/vdso64/vgetrandom-chacha.S
@@ -4,7 +4,7 @@
*/
#include <linux/linkage.h>
-#include <asm/frame.h>
+#include <asm/dwarf2.h>
.section .rodata, "a"
.align 16
@@ -22,7 +22,7 @@ CONSTANTS: .octa 0x6b20657479622d323320646e61707865
* rcx: number of 64-byte blocks to write to output
*/
SYM_FUNC_START(__arch_chacha20_blocks_nostack)
-
+ CFI_STARTPROC
.set output, %rdi
.set key, %rsi
.set counter, %rdx
@@ -175,4 +175,5 @@ SYM_FUNC_START(__arch_chacha20_blocks_nostack)
pxor temp,temp
ret
+ CFI_ENDPROC
SYM_FUNC_END(__arch_chacha20_blocks_nostack)
--
2.51.0
^ permalink raw reply related
* [PATCH v9 3/6] x86/asm: Use CFI_* macros in SYM_FUNC_* macros so they can be added to VDSO
From: Jens Remus @ 2026-02-11 14:13 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
Steven Rostedt
Cc: Jens Remus, Josh Poimboeuf, Masami Hiramatsu, Mathieu Desnoyers,
Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
H. Peter Anvin, Liam R. Howlett, Lorenzo Stoakes, Michal Hocko,
Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
Heiko Carstens, Vasily Gorbik, Steven Rostedt (Google)
In-Reply-To: <20260211141357.271402-1-jremus@linux.ibm.com>
From: Josh Poimboeuf <jpoimboe@kernel.org>
Add CFI_STARTPROC and CFI_ENDPROC annotations to the SYM_FUNC_* macros
so the VDSO asm functions don't need to add them manually. Note this
only affects VDSO, the CFI_* macros are empty for the kernel proper.
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Acked-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
arch/x86/entry/vdso/common/vdso-layout.lds.S | 2 +-
.../x86/entry/vdso/vdso64/vgetrandom-chacha.S | 2 --
arch/x86/entry/vdso/vdso64/vsgx.S | 4 ---
arch/x86/include/asm/linkage.h | 33 +++++++++++++++----
arch/x86/include/asm/vdso.h | 1 -
5 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/arch/x86/entry/vdso/common/vdso-layout.lds.S b/arch/x86/entry/vdso/common/vdso-layout.lds.S
index a1e30be3e83d..856b8b9d278c 100644
--- a/arch/x86/entry/vdso/common/vdso-layout.lds.S
+++ b/arch/x86/entry/vdso/common/vdso-layout.lds.S
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm/vdso.h>
+#include <asm/page_types.h>
#include <asm/vdso/vsyscall.h>
#include <vdso/datapage.h>
diff --git a/arch/x86/entry/vdso/vdso64/vgetrandom-chacha.S b/arch/x86/entry/vdso/vdso64/vgetrandom-chacha.S
index cc82da9216fb..a33212594731 100644
--- a/arch/x86/entry/vdso/vdso64/vgetrandom-chacha.S
+++ b/arch/x86/entry/vdso/vdso64/vgetrandom-chacha.S
@@ -22,7 +22,6 @@ CONSTANTS: .octa 0x6b20657479622d323320646e61707865
* rcx: number of 64-byte blocks to write to output
*/
SYM_FUNC_START(__arch_chacha20_blocks_nostack)
- CFI_STARTPROC
.set output, %rdi
.set key, %rsi
.set counter, %rdx
@@ -175,5 +174,4 @@ SYM_FUNC_START(__arch_chacha20_blocks_nostack)
pxor temp,temp
ret
- CFI_ENDPROC
SYM_FUNC_END(__arch_chacha20_blocks_nostack)
diff --git a/arch/x86/entry/vdso/vdso64/vsgx.S b/arch/x86/entry/vdso/vdso64/vsgx.S
index 37a3d4c02366..c0342238c976 100644
--- a/arch/x86/entry/vdso/vdso64/vsgx.S
+++ b/arch/x86/entry/vdso/vdso64/vsgx.S
@@ -24,8 +24,6 @@
.section .text, "ax"
SYM_FUNC_START(__vdso_sgx_enter_enclave)
- /* Prolog */
- .cfi_startproc
push %rbp
.cfi_adjust_cfa_offset 8
.cfi_rel_offset %rbp, 0
@@ -143,8 +141,6 @@ SYM_FUNC_START(__vdso_sgx_enter_enclave)
jle .Lout
jmp .Lenter_enclave
- .cfi_endproc
-
_ASM_VDSO_EXTABLE_HANDLE(.Lenclu_eenter_eresume, .Lhandle_exception)
SYM_FUNC_END(__vdso_sgx_enter_enclave)
diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h
index 9d38ae744a2e..9d7f90c57451 100644
--- a/arch/x86/include/asm/linkage.h
+++ b/arch/x86/include/asm/linkage.h
@@ -40,6 +40,10 @@
#ifdef __ASSEMBLER__
+#ifndef LINKER_SCRIPT
+#include <asm/dwarf2.h>
+#endif
+
#if defined(CONFIG_MITIGATION_RETHUNK) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO)
#define RET jmp __x86_return_thunk
#else /* CONFIG_MITIGATION_RETPOLINE */
@@ -112,34 +116,51 @@
# define SYM_FUNC_ALIAS_MEMFUNC SYM_FUNC_ALIAS
#endif
+#define __SYM_FUNC_START \
+ CFI_STARTPROC ASM_NL
+
+#define __SYM_FUNC_END \
+ CFI_ENDPROC ASM_NL
+
/* SYM_TYPED_FUNC_START -- use for indirectly called globals, w/ CFI type */
#define SYM_TYPED_FUNC_START(name) \
SYM_TYPED_START(name, SYM_L_GLOBAL, SYM_F_ALIGN) \
+ __SYM_FUNC_START \
ENDBR
/* SYM_FUNC_START -- use for global functions */
#define SYM_FUNC_START(name) \
- SYM_START(name, SYM_L_GLOBAL, SYM_F_ALIGN)
+ SYM_START(name, SYM_L_GLOBAL, SYM_F_ALIGN) \
+ __SYM_FUNC_START
/* SYM_FUNC_START_NOALIGN -- use for global functions, w/o alignment */
#define SYM_FUNC_START_NOALIGN(name) \
- SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE)
+ SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) \
+ __SYM_FUNC_START
/* SYM_FUNC_START_LOCAL -- use for local functions */
#define SYM_FUNC_START_LOCAL(name) \
- SYM_START(name, SYM_L_LOCAL, SYM_F_ALIGN)
+ SYM_START(name, SYM_L_LOCAL, SYM_F_ALIGN) \
+ __SYM_FUNC_START
/* SYM_FUNC_START_LOCAL_NOALIGN -- use for local functions, w/o alignment */
#define SYM_FUNC_START_LOCAL_NOALIGN(name) \
- SYM_START(name, SYM_L_LOCAL, SYM_A_NONE)
+ SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) \
+ __SYM_FUNC_START
/* SYM_FUNC_START_WEAK -- use for weak functions */
#define SYM_FUNC_START_WEAK(name) \
- SYM_START(name, SYM_L_WEAK, SYM_F_ALIGN)
+ SYM_START(name, SYM_L_WEAK, SYM_F_ALIGN) \
+ __SYM_FUNC_START
/* SYM_FUNC_START_WEAK_NOALIGN -- use for weak functions, w/o alignment */
#define SYM_FUNC_START_WEAK_NOALIGN(name) \
- SYM_START(name, SYM_L_WEAK, SYM_A_NONE)
+ SYM_START(name, SYM_L_WEAK, SYM_A_NONE) \
+ __SYM_FUNC_START
+
+#define SYM_FUNC_END(name) \
+ __SYM_FUNC_END \
+ SYM_END(name, SYM_T_FUNC)
/*
* Expose 'sym' to the startup code in arch/x86/boot/startup/, by emitting an
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h
index e8afbe9faa5b..498ac423741c 100644
--- a/arch/x86/include/asm/vdso.h
+++ b/arch/x86/include/asm/vdso.h
@@ -2,7 +2,6 @@
#ifndef _ASM_X86_VDSO_H
#define _ASM_X86_VDSO_H
-#include <asm/page_types.h>
#include <linux/linkage.h>
#include <linux/init.h>
--
2.51.0
^ permalink raw reply related
* [PATCH v9 6/6] x86/vdso: Enable sframe generation in VDSO
From: Jens Remus @ 2026-02-11 14:13 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
Steven Rostedt
Cc: Jens Remus, Josh Poimboeuf, Masami Hiramatsu, Mathieu Desnoyers,
Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
H. Peter Anvin, Liam R. Howlett, Lorenzo Stoakes, Michal Hocko,
Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
Heiko Carstens, Vasily Gorbik, Steven Rostedt (Google)
In-Reply-To: <20260211141357.271402-1-jremus@linux.ibm.com>
From: Josh Poimboeuf <jpoimboe@kernel.org>
Enable .sframe generation in the VDSO library so kernel and user space
can unwind through it.
Starting with binutils 2.46 both GNU assembler and GNU linker
exclusively support generating and merging .sframe in SFrame V3 format.
For x86 SFrame is only supported for x86-64. Not for x86-32 nor x32.
Test whether the assembler supports option '--gsframe-3' to explicitly
select SFrame V3 format. Note that testing using Kconfig macro
'as-option' is not sufficient, as GNU assembler will accept the option
for any target, regardless of whether it is actually capable to generate
.sframe for it, as long the input does not trigger the generation.
Therefore it is necessary to use Kconfig macro 'as-instr' to provide
minimal CFI directives that trigger generation of .sframe.
For x86-64 VDSO, only if supported by the assembler, generate .sframe,
collect it, mark it as KEEP, and generate a GNU_SFRAME program table
entry.
For x86-32 and x32 VDSOs, given SFrame is not supported, do not generate
any .sframe nor GNU_SFRAME program table entry. Instead explicitly
discard any .sframe. The latter is required for x32 VDSO, as it is
built from x86-64 VDSO objects (potentially with .sframe) converted to
x32. In this regard discarding .sframe also prevents potential
issues with linkers, such as GNU linker prior to binutils 2.46 commit
7487c98ff07a ("x32: Allow R_X86_64_PC64 for SFrame V3"), that do not
support R_X86_64_PC64 relocations in x32, like those found in .sframe
in SFrame V3 format.
[ Jens Remus: Add support for SFrame V3. Prevent GNU_SFRAME program
table entry to empty .sframe section. Reword commit message. ]
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
Notes (jremus):
Changes in v9:
- Always define KEEP_SFRAME to either true/false in specific VDSO linker
scripts and use #if instead of #ifdef in common one. (Peter)
- Reword commit message to provide more details.
arch/Kconfig | 7 +++++++
arch/x86/entry/vdso/common/vdso-layout.lds.S | 15 +++++++++++++++
arch/x86/entry/vdso/vdso32/vdso32.lds.S | 3 +++
arch/x86/entry/vdso/vdso64/Makefile | 1 +
arch/x86/entry/vdso/vdso64/vdso64.lds.S | 2 ++
arch/x86/entry/vdso/vdso64/vdsox32.lds.S | 6 ++++++
6 files changed, 34 insertions(+)
diff --git a/arch/Kconfig b/arch/Kconfig
index 31220f512b16..8170e492a44c 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -479,6 +479,13 @@ config HAVE_HARDLOCKUP_DETECTOR_ARCH
It uses the same command line parameters, and sysctl interface,
as the generic hardlockup detectors.
+config AS_SFRAME
+ bool
+
+config AS_SFRAME3
+ def_bool $(as-instr,.cfi_startproc\n.cfi_endproc,-Wa$(comma)--gsframe-3)
+ select AS_SFRAME
+
config UNWIND_USER
bool
diff --git a/arch/x86/entry/vdso/common/vdso-layout.lds.S b/arch/x86/entry/vdso/common/vdso-layout.lds.S
index 856b8b9d278c..c486b07b195a 100644
--- a/arch/x86/entry/vdso/common/vdso-layout.lds.S
+++ b/arch/x86/entry/vdso/common/vdso-layout.lds.S
@@ -60,6 +60,13 @@ SECTIONS
*(.eh_frame.*)
} :text
+#if KEEP_SFRAME
+ .sframe : {
+ KEEP (*(.sframe))
+ *(.sframe.*)
+ } :text :sframe
+#endif
+
/*
* Text is well-separated from actual data: there's plenty of
* stuff that isn't used at runtime in between.
@@ -80,6 +87,10 @@ SECTIONS
*(.discard)
*(.discard.*)
*(__bug_table)
+#if !KEEP_SFRAME
+ *(.sframe)
+ *(.sframe.*)
+#endif
}
}
@@ -89,6 +100,7 @@ SECTIONS
#define PT_GNU_EH_FRAME 0x6474e550
#define PT_GNU_STACK 0x6474e551
#define PT_GNU_PROPERTY 0x6474e553
+#define PT_GNU_SFRAME 0x6474e554
/*
* We must supply the ELF program headers explicitly to get just one
@@ -104,6 +116,9 @@ PHDRS
dynamic PT_DYNAMIC PF_R;
note PT_NOTE PF_R;
eh_frame_hdr PT_GNU_EH_FRAME PF_R;
+#if KEEP_SFRAME
+ sframe PT_GNU_SFRAME PF_R;
+#endif
gnu_stack PT_GNU_STACK PF_RW;
gnu_property PT_GNU_PROPERTY PF_R;
}
diff --git a/arch/x86/entry/vdso/vdso32/vdso32.lds.S b/arch/x86/entry/vdso/vdso32/vdso32.lds.S
index 8a853543fc0d..3a161f8e9c2d 100644
--- a/arch/x86/entry/vdso/vdso32/vdso32.lds.S
+++ b/arch/x86/entry/vdso/vdso32/vdso32.lds.S
@@ -11,6 +11,9 @@
#define BUILD_VDSO32
+/* Discard .sframe if any. SFrame does not support x86-32. */
+#define KEEP_SFRAME 0
+
#include "common/vdso-layout.lds.S"
/* The ELF entry point can be used to set the AT_SYSINFO value. */
diff --git a/arch/x86/entry/vdso/vdso64/Makefile b/arch/x86/entry/vdso/vdso64/Makefile
index bfffaf1aeecc..459f8026531e 100644
--- a/arch/x86/entry/vdso/vdso64/Makefile
+++ b/arch/x86/entry/vdso/vdso64/Makefile
@@ -14,6 +14,7 @@ vobjs-$(CONFIG_X86_SGX) += vsgx.o
# Compilation flags
flags-y := -DBUILD_VDSO64 -m64 -mcmodel=small
+flags-$(CONFIG_AS_SFRAME3) += -Wa,--gsframe-3
# The location of this include matters!
include $(src)/../common/Makefile.include
diff --git a/arch/x86/entry/vdso/vdso64/vdso64.lds.S b/arch/x86/entry/vdso/vdso64/vdso64.lds.S
index 5ce3f2b6373a..6685cf385fc1 100644
--- a/arch/x86/entry/vdso/vdso64/vdso64.lds.S
+++ b/arch/x86/entry/vdso/vdso64/vdso64.lds.S
@@ -9,6 +9,8 @@
#define BUILD_VDSO64
+#define KEEP_SFRAME IS_ENABLED(CONFIG_AS_SFRAME)
+
#include "common/vdso-layout.lds.S"
/*
diff --git a/arch/x86/entry/vdso/vdso64/vdsox32.lds.S b/arch/x86/entry/vdso/vdso64/vdsox32.lds.S
index 3dbd20c8dacc..5270fd0bdd0f 100644
--- a/arch/x86/entry/vdso/vdso64/vdsox32.lds.S
+++ b/arch/x86/entry/vdso/vdso64/vdsox32.lds.S
@@ -9,6 +9,12 @@
#define BUILD_VDSOX32
+/*
+ * Discard .sframe from x86-64 compiles. SFrame does not support x32 and
+ * it contains R_X86_64_PC64 relocations, which linkers may not expect.
+ */
+#define KEEP_SFRAME 0
+
#include "common/vdso-layout.lds.S"
/*
--
2.51.0
^ permalink raw reply related
* [PATCH v9 2/6] x86/asm: Avoid emitting DWARF CFI for non-VDSO
From: Jens Remus @ 2026-02-11 14:13 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
Steven Rostedt
Cc: Jens Remus, Josh Poimboeuf, Masami Hiramatsu, Mathieu Desnoyers,
Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
H. Peter Anvin, Liam R. Howlett, Lorenzo Stoakes, Michal Hocko,
Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
Heiko Carstens, Vasily Gorbik, Steven Rostedt (Google)
In-Reply-To: <20260211141357.271402-1-jremus@linux.ibm.com>
From: Josh Poimboeuf <jpoimboe@kernel.org>
It was decided years ago that .cfi_* annotations aren't maintainable in
the kernel. They were replaced by objtool unwind hints. For the kernel
proper, ensure the CFI_* macros don't do anything.
On the other hand the VDSO library *does* use them, so user space can
unwind through it.
Make sure these macros only work for VDSO. They aren't actually being
used outside of VDSO anyway, so there's no functional change.
[ Jens Remus: Define CFI_SIGNAL_FRAME for !BUILD_VDSO. ]
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Acked-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
arch/x86/include/asm/dwarf2.h | 52 ++++++++++++++++++++++++-----------
1 file changed, 36 insertions(+), 16 deletions(-)
diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h
index 09c9684d3ad6..13e2e64ef265 100644
--- a/arch/x86/include/asm/dwarf2.h
+++ b/arch/x86/include/asm/dwarf2.h
@@ -6,6 +6,15 @@
#warning "asm/dwarf2.h should be only included in pure assembly files"
#endif
+#ifdef BUILD_VDSO
+
+ /*
+ * For the vDSO, emit both runtime unwind information and debug
+ * symbols for the .dbg file.
+ */
+
+ .cfi_sections .eh_frame, .debug_frame
+
#define CFI_STARTPROC .cfi_startproc
#define CFI_ENDPROC .cfi_endproc
#define CFI_DEF_CFA .cfi_def_cfa
@@ -22,21 +31,32 @@
#define CFI_ESCAPE .cfi_escape
#define CFI_SIGNAL_FRAME .cfi_signal_frame
-#ifndef BUILD_VDSO
- /*
- * Emit CFI data in .debug_frame sections, not .eh_frame sections.
- * The latter we currently just discard since we don't do DWARF
- * unwinding at runtime. So only the offline DWARF information is
- * useful to anyone. Note we should not use this directive if we
- * ever decide to enable DWARF unwinding at runtime.
- */
- .cfi_sections .debug_frame
-#else
- /*
- * For the vDSO, emit both runtime unwind information and debug
- * symbols for the .dbg file.
- */
- .cfi_sections .eh_frame, .debug_frame
-#endif
+#else /* !BUILD_VDSO */
+
+/*
+ * On x86, these macros aren't used outside VDSO. As well they shouldn't be:
+ * they're fragile and very difficult to maintain.
+ */
+
+.macro nocfi args:vararg
+.endm
+
+#define CFI_STARTPROC nocfi
+#define CFI_ENDPROC nocfi
+#define CFI_DEF_CFA nocfi
+#define CFI_DEF_CFA_REGISTER nocfi
+#define CFI_DEF_CFA_OFFSET nocfi
+#define CFI_ADJUST_CFA_OFFSET nocfi
+#define CFI_OFFSET nocfi
+#define CFI_REL_OFFSET nocfi
+#define CFI_REGISTER nocfi
+#define CFI_RESTORE nocfi
+#define CFI_REMEMBER_STATE nocfi
+#define CFI_RESTORE_STATE nocfi
+#define CFI_UNDEFINED nocfi
+#define CFI_ESCAPE nocfi
+#define CFI_SIGNAL_FRAME nocfi
+
+#endif /* !BUILD_VDSO */
#endif /* _ASM_X86_DWARF2_H */
--
2.51.0
^ permalink raw reply related
* [PATCH v9 0/6] x86/vdso: VDSO updates and fixes for sframes
From: Jens Remus @ 2026-02-11 14:13 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
Steven Rostedt
Cc: Jens Remus, Josh Poimboeuf, Masami Hiramatsu, Mathieu Desnoyers,
Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
H. Peter Anvin, Liam R. Howlett, Lorenzo Stoakes, Michal Hocko,
Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
Heiko Carstens, Vasily Gorbik
This enables generation of SFrame V3 stack trace information for VDSO on
x86-64. It's a continuation of Josh's and Steve's work:
https://lore.kernel.org/all/cover.1737511963.git.jpoimboe@kernel.org/
https://lore.kernel.org/all/20250425023750.669174660@goodmis.org/
This series focuses only on the VDSO code. They are helpful fixes
and updates that doesn't rely on sframes (although the last patch
is sframe related).
This series applies on top of tip:x86/entry:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/entry
Like the unwind user sframe series [1] it depends on the binutils 2.46
release to be used to build the VDSO with SFrame V3 stack trace
information (using the assembler option --gsframe-3).
[1]: [PATCH v13 00/18] unwind_deferred: Implement sframe handling,
https://lore.kernel.org/all/20260127150554.2760964-1-jremus@linux.ibm.com/
Changes in v9 (see indivicual patch notes):
- Always define KEEP_SFRAME to either true/false in specific VDSO linker
scripts and use #if instead of #ifdef in common one. (Peter)
- Reword patch 6 commit message to provide more details.
- Note: Binutils 2.46 with SFrame V3 support has been released.
Changes in v8:
- Discard .sframe for x32 and x86-32 VDSOs. (Josh/Indu)
- Define CFI_SIGNAL_FRAME for !BUILD_VDSO.
- Drop .cfi_sections .sframe in dwarf2.h in favor of the explicitly
specified more specific assembler option --gsframe-3.
- Incorporate missing changes and review feedback from Steven's v6
(I erroneously based my v6 on Steven's v5):
- Reword patch 3 commit subject to Steven's v6 one.
- Remove SYM_F_ALIGN in __vdso_sgx_enter_enclave(). (Josh)
Changes in v7:
- Rebase on H. Peter Anvin's vDSO changes on tip:x86/entry. (Peter)
- Simplify adding assembler option -Wa,--gsframe-3. Add for vdso64
only.
- Align to .eh_frame and mark .sframe as KEEP in vDSO linker script.
Note that GNU linker 2.46 will mark .sframe as KEEP in its default
linker script as well.
Changes in v6:
- SFrame V3 support (SFrame V2 is not supported).
- Prevent GNU_SFRAME program table entry to empty .sframe section.
- Integrate v5 review feedback. (Josh)
Regards,
Jens
Josh Poimboeuf (6):
x86/vdso: Fix DWARF generation for getrandom()
x86/asm: Avoid emitting DWARF CFI for non-VDSO
x86/asm: Use CFI_* macros in SYM_FUNC_* macros so they can be added to
VDSO
x86/vdso: Use SYM_FUNC_{START,END} in __kernel_vsyscall()
x86/vdso: Use CFI macros in __vdso_sgx_enter_enclave()
x86/vdso: Enable sframe generation in VDSO
arch/Kconfig | 7 +++
arch/x86/entry/vdso/common/vdso-layout.lds.S | 17 +++++-
arch/x86/entry/vdso/vdso32/system_call.S | 10 +---
arch/x86/entry/vdso/vdso32/vdso32.lds.S | 3 ++
arch/x86/entry/vdso/vdso64/Makefile | 1 +
arch/x86/entry/vdso/vdso64/vdso64.lds.S | 2 +
arch/x86/entry/vdso/vdso64/vdsox32.lds.S | 6 +++
.../x86/entry/vdso/vdso64/vgetrandom-chacha.S | 3 +-
arch/x86/entry/vdso/vdso64/vsgx.S | 18 +++----
arch/x86/include/asm/dwarf2.h | 52 +++++++++++++------
arch/x86/include/asm/linkage.h | 33 +++++++++---
arch/x86/include/asm/vdso.h | 1 -
12 files changed, 107 insertions(+), 46 deletions(-)
--
2.51.0
^ permalink raw reply
* Re: [PATCH v4 0/3] PCI Controller event and LTSSM tracepoint support
From: Shawn Lin @ 2026-02-11 13:13 UTC (permalink / raw)
To: Manivannan Sadhasivam, Bjorn Helgaas
Cc: shawn.lin, linux-rockchip, linux-pci, linux-trace-kernel,
linux-doc, Steven Rostedt, Masami Hiramatsu
In-Reply-To: <1769047340-113287-1-git-send-email-shawn.lin@rock-chips.com>
在 2026/01/22 星期四 10:02, Shawn Lin 写道:
> This patch-set adds new pci controller event and LTSSM tracepoint used by host drivers
> which provide LTSSM trace functionality. The first user is pcie-dw-rockchip with a 256
> Bytes FIFO for recording LTSSM transition.
>
Gentle ping...
> Testing
> =========
>
> This series was tested on RK3588/RK3588s EVB1 with NVMe SSD connected to PCIe3 and PCIe2
> root ports.
>
> echo 1 > /sys/kernel/debug/tracing/events/pci_controller/pcie_ltssm_state_transition/enable
> cat /sys/kernel/debug/tracing/trace_pipe
>
> # tracer: nop
> #
> # entries-in-buffer/entries-written: 64/64 #P:8
> #
> # _-----=> irqs-off/BH-disabled
> # / _----=> need-resched
> # | / _---=> hardirq/softirq
> # || / _--=> preempt-depth
> # ||| / _-=> migrate-disable
> # |||| / delay
> # TASK-PID CPU# ||||| TIMESTAMP FUNCTION
> # | | | ||||| | |
> kworker/0:0-9 [000] ..... 5.600194: pcie_ltssm_state_transition: dev: a40000000.pcie state: DETECT_ACT rate: Unknown
> kworker/0:0-9 [000] ..... 5.600198: pcie_ltssm_state_transition: dev: a40000000.pcie state: DETECT_WAIT rate: Unknown
> kworker/0:0-9 [000] ..... 5.600199: pcie_ltssm_state_transition: dev: a40000000.pcie state: DETECT_ACT rate: Unknown
> kworker/0:0-9 [000] ..... 5.600201: pcie_ltssm_state_transition: dev: a40000000.pcie state: POLL_ACTIVE rate: Unknown
> kworker/0:0-9 [000] ..... 5.600202: pcie_ltssm_state_transition: dev: a40000000.pcie state: POLL_CONFIG rate: Unknown
> kworker/0:0-9 [000] ..... 5.600204: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_LINKWD_START rate: Unknown
> kworker/0:0-9 [000] ..... 5.600206: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_LINKWD_ACEPT rate: Unknown
> kworker/0:0-9 [000] ..... 5.600207: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_LANENUM_WAI rate: Unknown
> kworker/0:0-9 [000] ..... 5.600208: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_LANENUM_ACEPT rate: Unknown
> kworker/0:0-9 [000] ..... 5.600210: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_COMPLETE rate: Unknown
> kworker/0:0-9 [000] ..... 5.600212: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_IDLE rate: Unknown
> kworker/0:0-9 [000] ..... 5.600213: pcie_ltssm_state_transition: dev: a40000000.pcie state: L0 rate: 2.5 GT/s
> kworker/0:0-9 [000] ..... 5.600214: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: Unknown
> kworker/0:0-9 [000] ..... 5.600216: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_RCVRCFG rate: Unknown
> kworker/0:0-9 [000] ..... 5.600217: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_SPEED rate: Unknown
> kworker/0:0-9 [000] ..... 5.600218: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: Unknown
> kworker/0:0-9 [000] ..... 5.600220: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_EQ1 rate: Unknown
> kworker/0:0-9 [000] ..... 5.600221: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_EQ2 rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600222: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_EQ3 rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600224: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600225: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_RCVRCFG rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600226: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_IDLE rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600227: pcie_ltssm_state_transition: dev: a40000000.pcie state: L0 rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600228: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600229: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_RCVRCFG rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600231: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_IDLE rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600232: pcie_ltssm_state_transition: dev: a40000000.pcie state: L0 rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600233: pcie_ltssm_state_transition: dev: a40000000.pcie state: L123_SEND_EIDLE rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600234: pcie_ltssm_state_transition: dev: a40000000.pcie state: L1_IDLE rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600236: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600237: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_RCVRCFG rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600238: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_IDLE rate: 8.0 GT/s
> kworker/0:0-9 [000] ..... 5.600239: pcie_ltssm_state_transition: dev: a40000000.pcie state: L0 rate: 8.0 GT/s
>
>
> Changes in v4:
> - use TRACE_EVENT_FN to notify when to start and stop the tracepoint,
> and export pci_ltssm_tp_enabled() for host drivers to use
> - skip trace if pci_ltssm_tp_enabled() is false.(Steven)
> - wrap into 80 columns(Bjorn)
>
> Changes in v3:
> - add TRACE_DEFINE_ENUM for all enums(Steven Rostedt)
> - Add toctree entry in Documentation/trace/index.rst(Bagas Sanjaya)
> - fix mismatch section underline length(Bagas Sanjaya)
> - Make example snippets in code block(Bagas Sanjaya)
> - warp context into 80 columns and fix the file name(Bjorn)
> - reorder variables(Mani)
> - rename loop to i; rename en to enable(Mani)
> - use FIELD_GET(Mani)
> - add comment about how the FIFO works(Mani)
>
> Changes in v2:
> - use tracepoint
>
> Shawn Lin (3):
> PCI: trace: Add PCI controller LTSSM transition tracepoint
> Documentation: tracing: Add PCI controller event documentation
> PCI: dw-rockchip: Add pcie_ltssm_state_transition trace support
>
> Documentation/trace/events-pci-controller.rst | 42 ++++++++++
> Documentation/trace/index.rst | 1 +
> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 111 ++++++++++++++++++++++++++
> drivers/pci/trace.c | 20 +++++
> include/linux/pci.h | 4 +
> include/trace/events/pci_controller.h | 57 +++++++++++++
> 6 files changed, 235 insertions(+)
> create mode 100644 Documentation/trace/events-pci-controller.rst
> create mode 100644 include/trace/events/pci_controller.h
>
^ permalink raw reply
* [PATCH 1/4] mm: introduce zone lock wrappers
From: Dmitry Ilvokhin @ 2026-02-11 15:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Brendan Jackman,
Johannes Weiner, Zi Yan, Oscar Salvador, Qi Zheng, Shakeel Butt,
Axel Rasmussen, Yuanchu Xie, Wei Xu
Cc: linux-kernel, linux-mm, linux-trace-kernel, linux-cxl,
kernel-team, Dmitry Ilvokhin
In-Reply-To: <cover.1770821420.git.d@ilvokhin.com>
Add thin wrappers around zone lock acquire/release operations. This
prepares the code for future tracepoint instrumentation without
modifying individual call sites.
Centralizing zone lock operations behind wrappers allows future
instrumentation or debugging hooks to be added without touching
all users.
No functional change intended. The wrappers are introduced in
preparation for subsequent patches and are not yet used.
Signed-off-by: Dmitry Ilvokhin <d@ilvokhin.com>
---
MAINTAINERS | 1 +
include/linux/zone_lock.h | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
create mode 100644 include/linux/zone_lock.h
diff --git a/MAINTAINERS b/MAINTAINERS
index b4088f7290be..680c9ae02d7e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16498,6 +16498,7 @@ F: include/linux/pgtable.h
F: include/linux/ptdump.h
F: include/linux/vmpressure.h
F: include/linux/vmstat.h
+F: include/linux/zone_lock.h
F: kernel/fork.c
F: mm/Kconfig
F: mm/debug.c
diff --git a/include/linux/zone_lock.h b/include/linux/zone_lock.h
new file mode 100644
index 000000000000..c531e26280e6
--- /dev/null
+++ b/include/linux/zone_lock.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_ZONE_LOCK_H
+#define _LINUX_ZONE_LOCK_H
+
+#include <linux/mmzone.h>
+#include <linux/spinlock.h>
+
+static inline void zone_lock_init(struct zone *zone)
+{
+ spin_lock_init(&zone->lock);
+}
+
+#define zone_lock_irqsave(zone, flags) \
+do { \
+ spin_lock_irqsave(&(zone)->lock, flags); \
+} while (0)
+
+#define zone_trylock_irqsave(zone, flags) \
+({ \
+ spin_trylock_irqsave(&(zone)->lock, flags); \
+})
+
+static inline void zone_unlock_irqrestore(struct zone *zone, unsigned long flags)
+{
+ spin_unlock_irqrestore(&zone->lock, flags);
+}
+
+static inline void zone_lock_irq(struct zone *zone)
+{
+ spin_lock_irq(&zone->lock);
+}
+
+static inline void zone_unlock_irq(struct zone *zone)
+{
+ spin_unlock_irq(&zone->lock);
+}
+
+#endif /* _LINUX_ZONE_LOCK_H */
--
2.47.3
^ permalink raw reply related
* [PATCH 0/4] mm: zone lock tracepoint instrumentation
From: Dmitry Ilvokhin @ 2026-02-11 15:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Brendan Jackman,
Johannes Weiner, Zi Yan, Oscar Salvador, Qi Zheng, Shakeel Butt,
Axel Rasmussen, Yuanchu Xie, Wei Xu
Cc: linux-kernel, linux-mm, linux-trace-kernel, linux-cxl,
kernel-team, Dmitry Ilvokhin
Zone lock contention can significantly impact allocation and
reclaim latency, as it is a central synchronization point in
the page allocator and reclaim paths. Improved visibility into
its behavior is therefore important for diagnosing performance
issues in memory-intensive workloads.
On some production workloads at Meta, we have observed noticeable
zone lock contention. Deeper analysis of lock holders and waiters
is currently difficult with existing instrumentation.
While generic lock contention_begin/contention_end tracepoints
cover the slow path, they do not provide sufficient visibility
into lock hold times. In particular, the lack of a release-side
event makes it difficult to identify long lock holders and
correlate them with waiters. As a result, distinguishing between
short bursts of contention and pathological long hold times
requires additional instrumentation.
This patch series adds dedicated tracepoint instrumentation to
zone lock, following the existing mmap_lock tracing model.
The goal is to enable detailed holder/waiter analysis and lock
hold time measurements without affecting the fast path when
tracing is disabled.
The series is structured as follows:
1. Introduce zone lock wrappers.
2. Mechanically convert zone lock users to the wrappers.
3. Convert compaction to use the wrappers (requires minor
restructuring of compact_lock_irqsave()).
4. Add zone lock tracepoints.
The tracepoints are added via lightweight inline helpers in the
wrappers. When tracing is disabled, the fast path remains
unchanged.
The compaction changes required abstracting compact_lock_irqsave() away from
raw spinlock_t. I chose a small tagged struct to handle both zone and LRU
locks uniformly. If there is a preferred alternative (e.g. splitting helpers
or using a different abstraction), I would appreciate feedback.
Dmitry Ilvokhin (4):
mm: introduce zone lock wrappers
mm: convert zone lock users to wrappers
mm: convert compaction to zone lock wrappers
mm: add tracepoints for zone lock
MAINTAINERS | 3 +
include/linux/zone_lock.h | 100 ++++++++++++++++++++++++++++
include/trace/events/zone_lock.h | 64 ++++++++++++++++++
mm/Makefile | 2 +-
mm/compaction.c | 108 +++++++++++++++++++++++++------
mm/memory_hotplug.c | 9 +--
mm/mm_init.c | 3 +-
mm/page_alloc.c | 73 ++++++++++-----------
mm/page_isolation.c | 19 +++---
mm/page_reporting.c | 13 ++--
mm/show_mem.c | 5 +-
mm/vmscan.c | 5 +-
mm/vmstat.c | 9 +--
mm/zone_lock.c | 31 +++++++++
14 files changed, 360 insertions(+), 84 deletions(-)
create mode 100644 include/linux/zone_lock.h
create mode 100644 include/trace/events/zone_lock.h
create mode 100644 mm/zone_lock.c
--
2.47.3
^ permalink raw reply
* [PATCH 2/4] mm: convert zone lock users to wrappers
From: Dmitry Ilvokhin @ 2026-02-11 15:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Brendan Jackman,
Johannes Weiner, Zi Yan, Oscar Salvador, Qi Zheng, Shakeel Butt,
Axel Rasmussen, Yuanchu Xie, Wei Xu
Cc: linux-kernel, linux-mm, linux-trace-kernel, linux-cxl,
kernel-team, Dmitry Ilvokhin
In-Reply-To: <cover.1770821420.git.d@ilvokhin.com>
Replace direct zone lock acquire/release operations with the
newly introduced wrappers.
The changes are purely mechanical substitutions. No functional change
intended. Locking semantics and ordering remain unchanged.
The compaction path is left unchanged for now and will be
handled separately in the following patch due to additional
non-trivial modifications.
Signed-off-by: Dmitry Ilvokhin <d@ilvokhin.com>
---
mm/memory_hotplug.c | 9 +++---
mm/mm_init.c | 3 +-
mm/page_alloc.c | 73 +++++++++++++++++++++++----------------------
mm/page_isolation.c | 19 ++++++------
mm/page_reporting.c | 13 ++++----
mm/show_mem.c | 5 ++--
mm/vmscan.c | 5 ++--
mm/vmstat.c | 9 +++---
8 files changed, 72 insertions(+), 64 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index bc805029da51..cfc0103fa50e 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -36,6 +36,7 @@
#include <linux/rmap.h>
#include <linux/module.h>
#include <linux/node.h>
+#include <linux/zone_lock.h>
#include <asm/tlbflush.h>
@@ -1190,9 +1191,9 @@ int online_pages(unsigned long pfn, unsigned long nr_pages,
* Fixup the number of isolated pageblocks before marking the sections
* onlining, such that undo_isolate_page_range() works correctly.
*/
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
zone->nr_isolate_pageblock += nr_pages / pageblock_nr_pages;
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
/*
* If this zone is not populated, then it is not in zonelist.
@@ -2041,9 +2042,9 @@ int offline_pages(unsigned long start_pfn, unsigned long nr_pages,
* effectively stale; nobody should be touching them. Fixup the number
* of isolated pageblocks, memory onlining will properly revert this.
*/
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
zone->nr_isolate_pageblock -= nr_pages / pageblock_nr_pages;
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
lru_cache_enable();
zone_pcp_enable(zone);
diff --git a/mm/mm_init.c b/mm/mm_init.c
index 1a29a719af58..426e5a0256f9 100644
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -32,6 +32,7 @@
#include <linux/vmstat.h>
#include <linux/kexec_handover.h>
#include <linux/hugetlb.h>
+#include <linux/zone_lock.h>
#include "internal.h"
#include "slab.h"
#include "shuffle.h"
@@ -1425,7 +1426,7 @@ static void __meminit zone_init_internals(struct zone *zone, enum zone_type idx,
zone_set_nid(zone, nid);
zone->name = zone_names[idx];
zone->zone_pgdat = NODE_DATA(nid);
- spin_lock_init(&zone->lock);
+ zone_lock_init(zone);
zone_seqlock_init(zone);
zone_pcp_init(zone);
}
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e4104973e22f..2c9fe30da7a1 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -54,6 +54,7 @@
#include <linux/delayacct.h>
#include <linux/cacheinfo.h>
#include <linux/pgalloc_tag.h>
+#include <linux/zone_lock.h>
#include <asm/div64.h>
#include "internal.h"
#include "shuffle.h"
@@ -1494,7 +1495,7 @@ static void free_pcppages_bulk(struct zone *zone, int count,
/* Ensure requested pindex is drained first. */
pindex = pindex - 1;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
while (count > 0) {
struct list_head *list;
@@ -1527,7 +1528,7 @@ static void free_pcppages_bulk(struct zone *zone, int count,
} while (count > 0 && !list_empty(list));
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
}
/* Split a multi-block free page into its individual pageblocks. */
@@ -1571,12 +1572,12 @@ static void free_one_page(struct zone *zone, struct page *page,
unsigned long flags;
if (unlikely(fpi_flags & FPI_TRYLOCK)) {
- if (!spin_trylock_irqsave(&zone->lock, flags)) {
+ if (!zone_trylock_irqsave(zone, flags)) {
add_page_to_zone_llist(zone, page, order);
return;
}
} else {
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
}
/* The lock succeeded. Process deferred pages. */
@@ -1594,7 +1595,7 @@ static void free_one_page(struct zone *zone, struct page *page,
}
}
split_large_buddy(zone, page, pfn, order, fpi_flags);
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
__count_vm_events(PGFREE, 1 << order);
}
@@ -2547,10 +2548,10 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
int i;
if (unlikely(alloc_flags & ALLOC_TRYLOCK)) {
- if (!spin_trylock_irqsave(&zone->lock, flags))
+ if (!zone_trylock_irqsave(zone, flags))
return 0;
} else {
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
}
for (i = 0; i < count; ++i) {
struct page *page = __rmqueue(zone, order, migratetype,
@@ -2570,7 +2571,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
*/
list_add_tail(&page->pcp_list, list);
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return i;
}
@@ -3235,10 +3236,10 @@ struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone,
do {
page = NULL;
if (unlikely(alloc_flags & ALLOC_TRYLOCK)) {
- if (!spin_trylock_irqsave(&zone->lock, flags))
+ if (!zone_trylock_irqsave(zone, flags))
return NULL;
} else {
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
}
if (alloc_flags & ALLOC_HIGHATOMIC)
page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC);
@@ -3257,11 +3258,11 @@ struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone,
page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC);
if (!page) {
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return NULL;
}
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
} while (check_new_pages(page, order));
__count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);
@@ -3448,7 +3449,7 @@ static void reserve_highatomic_pageblock(struct page *page, int order,
if (zone->nr_reserved_highatomic >= max_managed)
return;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
/* Recheck the nr_reserved_highatomic limit under the lock */
if (zone->nr_reserved_highatomic >= max_managed)
@@ -3470,7 +3471,7 @@ static void reserve_highatomic_pageblock(struct page *page, int order,
}
out_unlock:
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
}
/*
@@ -3503,7 +3504,7 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
pageblock_nr_pages)
continue;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
for (order = 0; order < NR_PAGE_ORDERS; order++) {
struct free_area *area = &(zone->free_area[order]);
unsigned long size;
@@ -3551,11 +3552,11 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
*/
WARN_ON_ONCE(ret == -1);
if (ret > 0) {
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return ret;
}
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
}
return false;
@@ -6435,7 +6436,7 @@ static void __setup_per_zone_wmarks(void)
for_each_zone(zone) {
u64 tmp;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
tmp = (u64)pages_min * zone_managed_pages(zone);
tmp = div64_ul(tmp, lowmem_pages);
if (is_highmem(zone) || zone_idx(zone) == ZONE_MOVABLE) {
@@ -6476,7 +6477,7 @@ static void __setup_per_zone_wmarks(void)
zone->_watermark[WMARK_PROMO] = high_wmark_pages(zone) + tmp;
trace_mm_setup_per_zone_wmarks(zone);
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
}
/* update totalreserve_pages */
@@ -7246,7 +7247,7 @@ struct page *alloc_contig_frozen_pages_noprof(unsigned long nr_pages,
zonelist = node_zonelist(nid, gfp_mask);
for_each_zone_zonelist_nodemask(zone, z, zonelist,
gfp_zone(gfp_mask), nodemask) {
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
pfn = ALIGN(zone->zone_start_pfn, nr_pages);
while (zone_spans_last_pfn(zone, pfn, nr_pages)) {
@@ -7260,18 +7261,18 @@ struct page *alloc_contig_frozen_pages_noprof(unsigned long nr_pages,
* allocation spinning on this lock, it may
* win the race and cause allocation to fail.
*/
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
ret = alloc_contig_frozen_range_noprof(pfn,
pfn + nr_pages,
ACR_FLAGS_NONE,
gfp_mask);
if (!ret)
return pfn_to_page(pfn);
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
}
pfn += nr_pages;
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
}
/*
* If we failed, retry the search, but treat regions with HugeTLB pages
@@ -7425,7 +7426,7 @@ unsigned long __offline_isolated_pages(unsigned long start_pfn,
offline_mem_sections(pfn, end_pfn);
zone = page_zone(pfn_to_page(pfn));
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
while (pfn < end_pfn) {
page = pfn_to_page(pfn);
/*
@@ -7455,7 +7456,7 @@ unsigned long __offline_isolated_pages(unsigned long start_pfn,
del_page_from_free_list(page, zone, order, MIGRATE_ISOLATE);
pfn += (1 << order);
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return end_pfn - start_pfn - already_offline;
}
@@ -7531,7 +7532,7 @@ bool take_page_off_buddy(struct page *page)
unsigned int order;
bool ret = false;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
for (order = 0; order < NR_PAGE_ORDERS; order++) {
struct page *page_head = page - (pfn & ((1 << order) - 1));
int page_order = buddy_order(page_head);
@@ -7552,7 +7553,7 @@ bool take_page_off_buddy(struct page *page)
if (page_count(page_head) > 0)
break;
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return ret;
}
@@ -7565,7 +7566,7 @@ bool put_page_back_buddy(struct page *page)
unsigned long flags;
bool ret = false;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
if (put_page_testzero(page)) {
unsigned long pfn = page_to_pfn(page);
int migratetype = get_pfnblock_migratetype(page, pfn);
@@ -7576,7 +7577,7 @@ bool put_page_back_buddy(struct page *page)
ret = true;
}
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return ret;
}
@@ -7625,7 +7626,7 @@ static void __accept_page(struct zone *zone, unsigned long *flags,
account_freepages(zone, -MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE);
__mod_zone_page_state(zone, NR_UNACCEPTED, -MAX_ORDER_NR_PAGES);
__ClearPageUnaccepted(page);
- spin_unlock_irqrestore(&zone->lock, *flags);
+ zone_unlock_irqrestore(zone, *flags);
accept_memory(page_to_phys(page), PAGE_SIZE << MAX_PAGE_ORDER);
@@ -7637,9 +7638,9 @@ void accept_page(struct page *page)
struct zone *zone = page_zone(page);
unsigned long flags;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
if (!PageUnaccepted(page)) {
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return;
}
@@ -7652,11 +7653,11 @@ static bool try_to_accept_memory_one(struct zone *zone)
unsigned long flags;
struct page *page;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
page = list_first_entry_or_null(&zone->unaccepted_pages,
struct page, lru);
if (!page) {
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return false;
}
@@ -7713,12 +7714,12 @@ static bool __free_unaccepted(struct page *page)
if (!lazy_accept)
return false;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
list_add_tail(&page->lru, &zone->unaccepted_pages);
account_freepages(zone, MAX_ORDER_NR_PAGES, MIGRATE_MOVABLE);
__mod_zone_page_state(zone, NR_UNACCEPTED, MAX_ORDER_NR_PAGES);
__SetPageUnaccepted(page);
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return true;
}
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index c48ff5c00244..56a272f38b66 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -10,6 +10,7 @@
#include <linux/hugetlb.h>
#include <linux/page_owner.h>
#include <linux/migrate.h>
+#include <linux/zone_lock.h>
#include "internal.h"
#define CREATE_TRACE_POINTS
@@ -173,7 +174,7 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode,
if (PageUnaccepted(page))
accept_page(page);
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
/*
* We assume the caller intended to SET migrate type to isolate.
@@ -181,7 +182,7 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode,
* set it before us.
*/
if (is_migrate_isolate_page(page)) {
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return -EBUSY;
}
@@ -200,15 +201,15 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode,
mode);
if (!unmovable) {
if (!pageblock_isolate_and_move_free_pages(zone, page)) {
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return -EBUSY;
}
zone->nr_isolate_pageblock++;
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
return 0;
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
if (mode == PB_ISOLATE_MODE_MEM_OFFLINE) {
/*
* printk() with zone->lock held will likely trigger a
@@ -229,7 +230,7 @@ static void unset_migratetype_isolate(struct page *page)
struct page *buddy;
zone = page_zone(page);
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
if (!is_migrate_isolate_page(page))
goto out;
@@ -280,7 +281,7 @@ static void unset_migratetype_isolate(struct page *page)
}
zone->nr_isolate_pageblock--;
out:
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
}
static inline struct page *
@@ -641,9 +642,9 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,
/* Check all pages are free or marked as ISOLATED */
zone = page_zone(page);
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
pfn = __test_page_isolated_in_pageblock(start_pfn, end_pfn, mode);
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
ret = pfn < end_pfn ? -EBUSY : 0;
diff --git a/mm/page_reporting.c b/mm/page_reporting.c
index 8a03effda749..ac2ac8fd0487 100644
--- a/mm/page_reporting.c
+++ b/mm/page_reporting.c
@@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/scatterlist.h>
+#include <linux/zone_lock.h>
#include "page_reporting.h"
#include "internal.h"
@@ -161,7 +162,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,
if (list_empty(list))
return err;
- spin_lock_irq(&zone->lock);
+ zone_lock_irq(zone);
/*
* Limit how many calls we will be making to the page reporting
@@ -219,7 +220,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,
list_rotate_to_front(&page->lru, list);
/* release lock before waiting on report processing */
- spin_unlock_irq(&zone->lock);
+ zone_unlock_irq(zone);
/* begin processing pages in local list */
err = prdev->report(prdev, sgl, PAGE_REPORTING_CAPACITY);
@@ -231,7 +232,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,
budget--;
/* reacquire zone lock and resume processing */
- spin_lock_irq(&zone->lock);
+ zone_lock_irq(zone);
/* flush reported pages from the sg list */
page_reporting_drain(prdev, sgl, PAGE_REPORTING_CAPACITY, !err);
@@ -251,7 +252,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,
if (!list_entry_is_head(next, list, lru) && !list_is_first(&next->lru, list))
list_rotate_to_front(&next->lru, list);
- spin_unlock_irq(&zone->lock);
+ zone_unlock_irq(zone);
return err;
}
@@ -296,9 +297,9 @@ page_reporting_process_zone(struct page_reporting_dev_info *prdev,
err = prdev->report(prdev, sgl, leftover);
/* flush any remaining pages out from the last report */
- spin_lock_irq(&zone->lock);
+ zone_lock_irq(zone);
page_reporting_drain(prdev, sgl, leftover, !err);
- spin_unlock_irq(&zone->lock);
+ zone_unlock_irq(zone);
}
return err;
diff --git a/mm/show_mem.c b/mm/show_mem.c
index 24078ac3e6bc..245beca127af 100644
--- a/mm/show_mem.c
+++ b/mm/show_mem.c
@@ -14,6 +14,7 @@
#include <linux/mmzone.h>
#include <linux/swap.h>
#include <linux/vmstat.h>
+#include <linux/zone_lock.h>
#include "internal.h"
#include "swap.h"
@@ -363,7 +364,7 @@ static void show_free_areas(unsigned int filter, nodemask_t *nodemask, int max_z
show_node(zone);
printk(KERN_CONT "%s: ", zone->name);
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
for (order = 0; order < NR_PAGE_ORDERS; order++) {
struct free_area *area = &zone->free_area[order];
int type;
@@ -377,7 +378,7 @@ static void show_free_areas(unsigned int filter, nodemask_t *nodemask, int max_z
types[order] |= 1 << type;
}
}
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
for (order = 0; order < NR_PAGE_ORDERS; order++) {
printk(KERN_CONT "%lu*%lukB ",
nr[order], K(1UL) << order);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 973ffb9813ea..9fe5c41e0e0a 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -58,6 +58,7 @@
#include <linux/random.h>
#include <linux/mmu_notifier.h>
#include <linux/parser.h>
+#include <linux/zone_lock.h>
#include <asm/tlbflush.h>
#include <asm/div64.h>
@@ -7129,9 +7130,9 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int highest_zoneidx)
/* Increments are under the zone lock */
zone = pgdat->node_zones + i;
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
zone->watermark_boost -= min(zone->watermark_boost, zone_boosts[i]);
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
}
/*
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 99270713e0c1..06b27255a626 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -28,6 +28,7 @@
#include <linux/mm_inline.h>
#include <linux/page_owner.h>
#include <linux/sched/isolation.h>
+#include <linux/zone_lock.h>
#include "internal.h"
@@ -1535,10 +1536,10 @@ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
continue;
if (!nolock)
- spin_lock_irqsave(&zone->lock, flags);
+ zone_lock_irqsave(zone, flags);
print(m, pgdat, zone);
if (!nolock)
- spin_unlock_irqrestore(&zone->lock, flags);
+ zone_unlock_irqrestore(zone, flags);
}
}
#endif
@@ -1603,9 +1604,9 @@ static void pagetypeinfo_showfree_print(struct seq_file *m,
}
}
seq_printf(m, "%s%6lu ", overflow ? ">" : "", freecount);
- spin_unlock_irq(&zone->lock);
+ zone_unlock_irq(zone);
cond_resched();
- spin_lock_irq(&zone->lock);
+ zone_lock_irq(zone);
}
seq_putc(m, '\n');
}
--
2.47.3
^ permalink raw reply related
* [PATCH 3/4] mm: convert compaction to zone lock wrappers
From: Dmitry Ilvokhin @ 2026-02-11 15:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Brendan Jackman,
Johannes Weiner, Zi Yan, Oscar Salvador, Qi Zheng, Shakeel Butt,
Axel Rasmussen, Yuanchu Xie, Wei Xu
Cc: linux-kernel, linux-mm, linux-trace-kernel, linux-cxl,
kernel-team, Dmitry Ilvokhin
In-Reply-To: <cover.1770821420.git.d@ilvokhin.com>
Compaction uses compact_lock_irqsave(), which currently operates
on a raw spinlock_t pointer so that it can be used for both
zone->lock and lru_lock. Since zone lock operations are now wrapped,
compact_lock_irqsave() can no longer operate directly on a spinlock_t
when the lock belongs to a zone.
Introduce struct compact_lock to abstract the underlying lock type. The
structure carries a lock type enum and a union holding either a zone
pointer or a raw spinlock_t pointer, and dispatches to the appropriate
lock/unlock helper.
No functional change intended.
Signed-off-by: Dmitry Ilvokhin <d@ilvokhin.com>
---
mm/compaction.c | 108 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 89 insertions(+), 19 deletions(-)
diff --git a/mm/compaction.c b/mm/compaction.c
index 1e8f8eca318c..1b000d2b95b2 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -24,6 +24,7 @@
#include <linux/page_owner.h>
#include <linux/psi.h>
#include <linux/cpuset.h>
+#include <linux/zone_lock.h>
#include "internal.h"
#ifdef CONFIG_COMPACTION
@@ -493,6 +494,65 @@ static bool test_and_set_skip(struct compact_control *cc, struct page *page)
}
#endif /* CONFIG_COMPACTION */
+enum compact_lock_type {
+ COMPACT_LOCK_ZONE,
+ COMPACT_LOCK_RAW_SPINLOCK,
+};
+
+struct compact_lock {
+ enum compact_lock_type type;
+ union {
+ struct zone *zone;
+ spinlock_t *lock; /* Reference to lru lock */
+ };
+};
+
+static bool compact_do_zone_trylock_irqsave(struct zone *zone,
+ unsigned long *flags)
+{
+ return zone_trylock_irqsave(zone, *flags);
+}
+
+static bool compact_do_raw_trylock_irqsave(spinlock_t *lock,
+ unsigned long *flags)
+{
+ return spin_trylock_irqsave(lock, *flags);
+}
+
+static bool compact_do_trylock_irqsave(struct compact_lock lock,
+ unsigned long *flags)
+{
+ if (lock.type == COMPACT_LOCK_ZONE)
+ return compact_do_zone_trylock_irqsave(lock.zone, flags);
+
+ return compact_do_raw_trylock_irqsave(lock.lock, flags);
+}
+
+static void compact_do_zone_lock_irqsave(struct zone *zone,
+ unsigned long *flags)
+__acquires(zone->lock)
+{
+ zone_lock_irqsave(zone, *flags);
+}
+
+static void compact_do_raw_lock_irqsave(spinlock_t *lock,
+ unsigned long *flags)
+__acquires(lock)
+{
+ spin_lock_irqsave(lock, *flags);
+}
+
+static void compact_do_lock_irqsave(struct compact_lock lock,
+ unsigned long *flags)
+{
+ if (lock.type == COMPACT_LOCK_ZONE) {
+ compact_do_zone_lock_irqsave(lock.zone, flags);
+ return;
+ }
+
+ return compact_do_raw_lock_irqsave(lock.lock, flags);
+}
+
/*
* Compaction requires the taking of some coarse locks that are potentially
* very heavily contended. For async compaction, trylock and record if the
@@ -502,19 +562,19 @@ static bool test_and_set_skip(struct compact_control *cc, struct page *page)
*
* Always returns true which makes it easier to track lock state in callers.
*/
-static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags,
- struct compact_control *cc)
- __acquires(lock)
+static bool compact_lock_irqsave(struct compact_lock lock,
+ unsigned long *flags,
+ struct compact_control *cc)
{
/* Track if the lock is contended in async mode */
if (cc->mode == MIGRATE_ASYNC && !cc->contended) {
- if (spin_trylock_irqsave(lock, *flags))
+ if (compact_do_trylock_irqsave(lock, flags))
return true;
cc->contended = true;
}
- spin_lock_irqsave(lock, *flags);
+ compact_do_lock_irqsave(lock, flags);
return true;
}
@@ -530,11 +590,13 @@ static bool compact_lock_irqsave(spinlock_t *lock, unsigned long *flags,
* Returns true if compaction should abort due to fatal signal pending.
* Returns false when compaction can continue.
*/
-static bool compact_unlock_should_abort(spinlock_t *lock,
- unsigned long flags, bool *locked, struct compact_control *cc)
+static bool compact_unlock_should_abort(struct zone *zone,
+ unsigned long flags,
+ bool *locked,
+ struct compact_control *cc)
{
if (*locked) {
- spin_unlock_irqrestore(lock, flags);
+ zone_unlock_irqrestore(zone, flags);
*locked = false;
}
@@ -582,9 +644,8 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
* contention, to give chance to IRQs. Abort if fatal signal
* pending.
*/
- if (!(blockpfn % COMPACT_CLUSTER_MAX)
- && compact_unlock_should_abort(&cc->zone->lock, flags,
- &locked, cc))
+ if (!(blockpfn % COMPACT_CLUSTER_MAX) &&
+ compact_unlock_should_abort(cc->zone, flags, &locked, cc))
break;
nr_scanned++;
@@ -613,8 +674,12 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
/* If we already hold the lock, we can skip some rechecking. */
if (!locked) {
- locked = compact_lock_irqsave(&cc->zone->lock,
- &flags, cc);
+ struct compact_lock zol = {
+ .type = COMPACT_LOCK_ZONE,
+ .zone = cc->zone,
+ };
+
+ locked = compact_lock_irqsave(zol, &flags, cc);
/* Recheck this is a buddy page under lock */
if (!PageBuddy(page))
@@ -649,7 +714,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
}
if (locked)
- spin_unlock_irqrestore(&cc->zone->lock, flags);
+ zone_unlock_irqrestore(cc->zone, flags);
/*
* Be careful to not go outside of the pageblock.
@@ -1157,10 +1222,15 @@ isolate_migratepages_block(struct compact_control *cc, unsigned long low_pfn,
/* If we already hold the lock, we can skip some rechecking */
if (lruvec != locked) {
+ struct compact_lock zol = {
+ .type = COMPACT_LOCK_RAW_SPINLOCK,
+ .lock = &lruvec->lru_lock,
+ };
+
if (locked)
unlock_page_lruvec_irqrestore(locked, flags);
- compact_lock_irqsave(&lruvec->lru_lock, &flags, cc);
+ compact_lock_irqsave(zol, &flags, cc);
locked = lruvec;
lruvec_memcg_debug(lruvec, folio);
@@ -1555,7 +1625,7 @@ static void fast_isolate_freepages(struct compact_control *cc)
if (!area->nr_free)
continue;
- spin_lock_irqsave(&cc->zone->lock, flags);
+ zone_lock_irqsave(cc->zone, flags);
freelist = &area->free_list[MIGRATE_MOVABLE];
list_for_each_entry_reverse(freepage, freelist, buddy_list) {
unsigned long pfn;
@@ -1614,7 +1684,7 @@ static void fast_isolate_freepages(struct compact_control *cc)
}
}
- spin_unlock_irqrestore(&cc->zone->lock, flags);
+ zone_unlock_irqrestore(cc->zone, flags);
/* Skip fast search if enough freepages isolated */
if (cc->nr_freepages >= cc->nr_migratepages)
@@ -1988,7 +2058,7 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc)
if (!area->nr_free)
continue;
- spin_lock_irqsave(&cc->zone->lock, flags);
+ zone_lock_irqsave(cc->zone, flags);
freelist = &area->free_list[MIGRATE_MOVABLE];
list_for_each_entry(freepage, freelist, buddy_list) {
unsigned long free_pfn;
@@ -2021,7 +2091,7 @@ static unsigned long fast_find_migrateblock(struct compact_control *cc)
break;
}
}
- spin_unlock_irqrestore(&cc->zone->lock, flags);
+ zone_unlock_irqrestore(cc->zone, flags);
}
cc->total_migrate_scanned += nr_scanned;
--
2.47.3
^ permalink raw reply related
* [PATCH 4/4] mm: add tracepoints for zone lock
From: Dmitry Ilvokhin @ 2026-02-11 15:22 UTC (permalink / raw)
To: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Brendan Jackman,
Johannes Weiner, Zi Yan, Oscar Salvador, Qi Zheng, Shakeel Butt,
Axel Rasmussen, Yuanchu Xie, Wei Xu
Cc: linux-kernel, linux-mm, linux-trace-kernel, linux-cxl,
kernel-team, Dmitry Ilvokhin
In-Reply-To: <cover.1770821420.git.d@ilvokhin.com>
Add tracepoint instrumentation to zone lock acquire/release operations
via the previously introduced wrappers.
The implementation follows the mmap_lock tracepoint pattern: a
lightweight inline helper checks whether the tracepoint is enabled and
calls into an out-of-line helper when tracing is active. When
CONFIG_TRACING is disabled, helpers compile to empty inline stubs.
The fast path is unaffected when tracing is disabled.
Signed-off-by: Dmitry Ilvokhin <d@ilvokhin.com>
---
MAINTAINERS | 2 +
include/linux/zone_lock.h | 64 +++++++++++++++++++++++++++++++-
include/trace/events/zone_lock.h | 64 ++++++++++++++++++++++++++++++++
mm/Makefile | 2 +-
mm/zone_lock.c | 31 ++++++++++++++++
5 files changed, 161 insertions(+), 2 deletions(-)
create mode 100644 include/trace/events/zone_lock.h
create mode 100644 mm/zone_lock.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 680c9ae02d7e..711ffa15f4c3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16499,6 +16499,7 @@ F: include/linux/ptdump.h
F: include/linux/vmpressure.h
F: include/linux/vmstat.h
F: include/linux/zone_lock.h
+F: include/trace/events/zone_lock.h
F: kernel/fork.c
F: mm/Kconfig
F: mm/debug.c
@@ -16518,6 +16519,7 @@ F: mm/sparse.c
F: mm/util.c
F: mm/vmpressure.c
F: mm/vmstat.c
+F: mm/zone_lock.c
N: include/linux/page[-_]*
MEMORY MANAGEMENT - EXECMEM
diff --git a/include/linux/zone_lock.h b/include/linux/zone_lock.h
index c531e26280e6..cea41dd56324 100644
--- a/include/linux/zone_lock.h
+++ b/include/linux/zone_lock.h
@@ -4,6 +4,53 @@
#include <linux/mmzone.h>
#include <linux/spinlock.h>
+#include <linux/tracepoint-defs.h>
+
+DECLARE_TRACEPOINT(zone_lock_start_locking);
+DECLARE_TRACEPOINT(zone_lock_acquire_returned);
+DECLARE_TRACEPOINT(zone_lock_released);
+
+#ifdef CONFIG_TRACING
+
+void __zone_lock_do_trace_start_locking(struct zone *zone);
+void __zone_lock_do_trace_acquire_returned(struct zone *zone, bool success);
+void __zone_lock_do_trace_released(struct zone *zone);
+
+static inline void __zone_lock_trace_start_locking(struct zone *zone)
+{
+ if (tracepoint_enabled(zone_lock_start_locking))
+ __zone_lock_do_trace_start_locking(zone);
+}
+
+static inline void __zone_lock_trace_acquire_returned(struct zone *zone,
+ bool success)
+{
+ if (tracepoint_enabled(zone_lock_acquire_returned))
+ __zone_lock_do_trace_acquire_returned(zone, success);
+}
+
+static inline void __zone_lock_trace_released(struct zone *zone)
+{
+ if (tracepoint_enabled(zone_lock_released))
+ __zone_lock_do_trace_released(zone);
+}
+
+#else /* !CONFIG_TRACING */
+
+static inline void __zone_lock_trace_start_locking(struct zone *zone)
+{
+}
+
+static inline void __zone_lock_trace_acquire_returned(struct zone *zone,
+ bool success)
+{
+}
+
+static inline void __zone_lock_trace_released(struct zone *zone)
+{
+}
+
+#endif /* CONFIG_TRACING */
static inline void zone_lock_init(struct zone *zone)
{
@@ -12,26 +59,41 @@ static inline void zone_lock_init(struct zone *zone)
#define zone_lock_irqsave(zone, flags) \
do { \
+ bool success = true; \
+ \
+ __zone_lock_trace_start_locking(zone); \
spin_lock_irqsave(&(zone)->lock, flags); \
+ __zone_lock_trace_acquire_returned(zone, success); \
} while (0)
#define zone_trylock_irqsave(zone, flags) \
({ \
- spin_trylock_irqsave(&(zone)->lock, flags); \
+ bool success; \
+ \
+ __zone_lock_trace_start_locking(zone); \
+ success = spin_trylock_irqsave(&(zone)->lock, flags); \
+ __zone_lock_trace_acquire_returned(zone, success); \
+ success; \
})
static inline void zone_unlock_irqrestore(struct zone *zone, unsigned long flags)
{
+ __zone_lock_trace_released(zone);
spin_unlock_irqrestore(&zone->lock, flags);
}
static inline void zone_lock_irq(struct zone *zone)
{
+ bool success = true;
+
+ __zone_lock_trace_start_locking(zone);
spin_lock_irq(&zone->lock);
+ __zone_lock_trace_acquire_returned(zone, success);
}
static inline void zone_unlock_irq(struct zone *zone)
{
+ __zone_lock_trace_released(zone);
spin_unlock_irq(&zone->lock);
}
diff --git a/include/trace/events/zone_lock.h b/include/trace/events/zone_lock.h
new file mode 100644
index 000000000000..3df82a8c0160
--- /dev/null
+++ b/include/trace/events/zone_lock.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM zone_lock
+
+#if !defined(_TRACE_ZONE_LOCK_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ZONE_LOCK_H
+
+#include <linux/tracepoint.h>
+#include <linux/types.h>
+
+struct zone;
+
+DECLARE_EVENT_CLASS(zone_lock,
+
+ TP_PROTO(struct zone *zone),
+
+ TP_ARGS(zone),
+
+ TP_STRUCT__entry(
+ __field(struct zone *, zone)
+ ),
+
+ TP_fast_assign(
+ __entry->zone = zone;
+ ),
+
+ TP_printk("zone=%p", __entry->zone)
+);
+
+#define DEFINE_ZONE_LOCK_EVENT(name) \
+ DEFINE_EVENT(zone_lock, name, \
+ TP_PROTO(struct zone *zone), \
+ TP_ARGS(zone))
+
+DEFINE_ZONE_LOCK_EVENT(zone_lock_start_locking);
+DEFINE_ZONE_LOCK_EVENT(zone_lock_released);
+
+TRACE_EVENT(zone_lock_acquire_returned,
+
+ TP_PROTO(struct zone *zone, bool success),
+
+ TP_ARGS(zone, success),
+
+ TP_STRUCT__entry(
+ __field(struct zone *, zone)
+ __field(bool, success)
+ ),
+
+ TP_fast_assign(
+ __entry->zone = zone;
+ __entry->success = success;
+ ),
+
+ TP_printk(
+ "zone=%p success=%s",
+ __entry->zone,
+ __entry->success ? "true" : "false"
+ )
+);
+
+#endif /* _TRACE_ZONE_LOCK_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/mm/Makefile b/mm/Makefile
index 0d85b10dbdde..fd891710c696 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -55,7 +55,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
mm_init.o percpu.o slab_common.o \
compaction.o show_mem.o \
interval_tree.o list_lru.o workingset.o \
- debug.o gup.o mmap_lock.o vma_init.o $(mmu-y)
+ debug.o gup.o mmap_lock.o zone_lock.o vma_init.o $(mmu-y)
# Give 'page_alloc' its own module-parameter namespace
page-alloc-y := page_alloc.o
diff --git a/mm/zone_lock.c b/mm/zone_lock.c
new file mode 100644
index 000000000000..f647fd2aca48
--- /dev/null
+++ b/mm/zone_lock.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+#define CREATE_TRACE_POINTS
+#include <trace/events/zone_lock.h>
+
+#include <linux/zone_lock.h>
+
+EXPORT_TRACEPOINT_SYMBOL(zone_lock_start_locking);
+EXPORT_TRACEPOINT_SYMBOL(zone_lock_acquire_returned);
+EXPORT_TRACEPOINT_SYMBOL(zone_lock_released);
+
+#ifdef CONFIG_TRACING
+
+void __zone_lock_do_trace_start_locking(struct zone *zone)
+{
+ trace_zone_lock_start_locking(zone);
+}
+EXPORT_SYMBOL(__zone_lock_do_trace_start_locking);
+
+void __zone_lock_do_trace_acquire_returned(struct zone *zone, bool success)
+{
+ trace_zone_lock_acquire_returned(zone, success);
+}
+EXPORT_SYMBOL(__zone_lock_do_trace_acquire_returned);
+
+void __zone_lock_do_trace_released(struct zone *zone)
+{
+ trace_zone_lock_released(zone);
+}
+EXPORT_SYMBOL(__zone_lock_do_trace_released);
+
+#endif /* CONFIG_TRACING */
--
2.47.3
^ permalink raw reply related
* Re: [PATCH v4 0/3] PCI Controller event and LTSSM tracepoint support
From: Manivannan Sadhasivam @ 2026-02-11 15:40 UTC (permalink / raw)
To: Shawn Lin
Cc: Bjorn Helgaas, linux-rockchip, linux-pci, linux-trace-kernel,
linux-doc, Steven Rostedt, Masami Hiramatsu
In-Reply-To: <9e06e69c-d10a-1f21-cbf7-204319549612@rock-chips.com>
On Wed, Feb 11, 2026 at 09:13:50PM +0800, Shawn Lin wrote:
> 在 2026/01/22 星期四 10:02, Shawn Lin 写道:
> > This patch-set adds new pci controller event and LTSSM tracepoint used by host drivers
> > which provide LTSSM trace functionality. The first user is pcie-dw-rockchip with a 256
> > Bytes FIFO for recording LTSSM transition.
> >
>
> Gentle ping...
>
Merge window is open now, so we can't accept any patches until -rc1. And I'm
also waiting for an Ack from Steven for the tracing part.
- Mani
> > Testing
> > =========
> >
> > This series was tested on RK3588/RK3588s EVB1 with NVMe SSD connected to PCIe3 and PCIe2
> > root ports.
> >
> > echo 1 > /sys/kernel/debug/tracing/events/pci_controller/pcie_ltssm_state_transition/enable
> > cat /sys/kernel/debug/tracing/trace_pipe
> >
> > # tracer: nop
> > #
> > # entries-in-buffer/entries-written: 64/64 #P:8
> > #
> > # _-----=> irqs-off/BH-disabled
> > # / _----=> need-resched
> > # | / _---=> hardirq/softirq
> > # || / _--=> preempt-depth
> > # ||| / _-=> migrate-disable
> > # |||| / delay
> > # TASK-PID CPU# ||||| TIMESTAMP FUNCTION
> > # | | | ||||| | |
> > kworker/0:0-9 [000] ..... 5.600194: pcie_ltssm_state_transition: dev: a40000000.pcie state: DETECT_ACT rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600198: pcie_ltssm_state_transition: dev: a40000000.pcie state: DETECT_WAIT rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600199: pcie_ltssm_state_transition: dev: a40000000.pcie state: DETECT_ACT rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600201: pcie_ltssm_state_transition: dev: a40000000.pcie state: POLL_ACTIVE rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600202: pcie_ltssm_state_transition: dev: a40000000.pcie state: POLL_CONFIG rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600204: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_LINKWD_START rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600206: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_LINKWD_ACEPT rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600207: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_LANENUM_WAI rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600208: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_LANENUM_ACEPT rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600210: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_COMPLETE rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600212: pcie_ltssm_state_transition: dev: a40000000.pcie state: CFG_IDLE rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600213: pcie_ltssm_state_transition: dev: a40000000.pcie state: L0 rate: 2.5 GT/s
> > kworker/0:0-9 [000] ..... 5.600214: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600216: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_RCVRCFG rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600217: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_SPEED rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600218: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600220: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_EQ1 rate: Unknown
> > kworker/0:0-9 [000] ..... 5.600221: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_EQ2 rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600222: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_EQ3 rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600224: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600225: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_RCVRCFG rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600226: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_IDLE rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600227: pcie_ltssm_state_transition: dev: a40000000.pcie state: L0 rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600228: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600229: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_RCVRCFG rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600231: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_IDLE rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600232: pcie_ltssm_state_transition: dev: a40000000.pcie state: L0 rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600233: pcie_ltssm_state_transition: dev: a40000000.pcie state: L123_SEND_EIDLE rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600234: pcie_ltssm_state_transition: dev: a40000000.pcie state: L1_IDLE rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600236: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_LOCK rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600237: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_RCVRCFG rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600238: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_IDLE rate: 8.0 GT/s
> > kworker/0:0-9 [000] ..... 5.600239: pcie_ltssm_state_transition: dev: a40000000.pcie state: L0 rate: 8.0 GT/s
> >
> >
> > Changes in v4:
> > - use TRACE_EVENT_FN to notify when to start and stop the tracepoint,
> > and export pci_ltssm_tp_enabled() for host drivers to use
> > - skip trace if pci_ltssm_tp_enabled() is false.(Steven)
> > - wrap into 80 columns(Bjorn)
> >
> > Changes in v3:
> > - add TRACE_DEFINE_ENUM for all enums(Steven Rostedt)
> > - Add toctree entry in Documentation/trace/index.rst(Bagas Sanjaya)
> > - fix mismatch section underline length(Bagas Sanjaya)
> > - Make example snippets in code block(Bagas Sanjaya)
> > - warp context into 80 columns and fix the file name(Bjorn)
> > - reorder variables(Mani)
> > - rename loop to i; rename en to enable(Mani)
> > - use FIELD_GET(Mani)
> > - add comment about how the FIFO works(Mani)
> >
> > Changes in v2:
> > - use tracepoint
> >
> > Shawn Lin (3):
> > PCI: trace: Add PCI controller LTSSM transition tracepoint
> > Documentation: tracing: Add PCI controller event documentation
> > PCI: dw-rockchip: Add pcie_ltssm_state_transition trace support
> >
> > Documentation/trace/events-pci-controller.rst | 42 ++++++++++
> > Documentation/trace/index.rst | 1 +
> > drivers/pci/controller/dwc/pcie-dw-rockchip.c | 111 ++++++++++++++++++++++++++
> > drivers/pci/trace.c | 20 +++++
> > include/linux/pci.h | 4 +
> > include/trace/events/pci_controller.h | 57 +++++++++++++
> > 6 files changed, 235 insertions(+)
> > create mode 100644 Documentation/trace/events-pci-controller.rst
> > create mode 100644 include/trace/events/pci_controller.h
> >
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH v6 2/4] tracing: Make the backup instance non-reusable
From: Steven Rostedt @ 2026-02-11 15:42 UTC (permalink / raw)
To: Masami Hiramatsu (Google)
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
In-Reply-To: <20260210141415.01a6907dcb558866e1abb994@kernel.org>
On Tue, 10 Feb 2026 14:14:15 +0900
Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:
> Hmm, OK. Now I found how sysfs handles it.
>
> /*
> * For regular files, if the opener has CAP_DAC_OVERRIDE, open(2)
> * succeeds regardless of the RW permissions. sysfs had an extra
> * layer of enforcement where open(2) fails with -EACCES regardless
> * of CAP_DAC_OVERRIDE if the permission doesn't have the
> * respective read or write access at all (none of S_IRUGO or
> * S_IWUGO) or the respective operation isn't implemented. The
> * following flag enables that behavior.
> */
> KERNFS_ROOT_EXTRA_OPEN_PERM_CHECK = 0x0002,
>
> So for the similar reason, I will make tracefs to check the permission
> even if CAP_DAC_OVERRIDE is set. (But this check should be done in general,
> instead of each open() operation)
>
I don't believe this is the same. This is about an instance being truly
read only. The instance is special, not the files. Note, permissions can
be changed by root too. After applying your patches, I did the following:
~# cd /sys/kernel/tracing/instances/backup/
~# ls -l current_tracer
-r--r----- 1 root root 0 Feb 11 10:29 current_tracer
~# cat current_tracer
nop
~# cat trace
# tracer: nop
#
# entries-in-buffer/entries-written: 0/0 #P:8
#
# _-----=> irqs-off/BH-disabled
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / _-=> migrate-disable
# |||| / delay
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
# | | | ||||| | |
~# chmod 664 current_tracer
~# ls -l current_tracer
-rw-rw-r-- 1 root root 0 Feb 11 10:29 current_tracer
~# echo function > current_tracer
~# cat current_tracer
function
~# cat trace
# tracer: function
#
# entries-in-buffer/entries-written: 1750306/2076556 #P:8
#
# _-----=> irqs-off/BH-disabled
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / _-=> migrate-disable
# |||| / delay
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
# | | | ||||| | |
bash-1056 [001] ..... 231.448852: mutex_unlock <-tracing_set_tracer
<idle>-0 [002] ...1. 231.448853: arch_cpu_idle_exit <-do_idle
##### CPU 7 buffer started ####
<idle>-0 [007] ...1. 231.448853: arch_cpu_idle_exit <-do_idle
bash-1056 [001] ..... 231.448854: __mutex_unlock_slowpath <-tracing_set_tracer
<idle>-0 [002] d..1. 231.448855: arch_cpu_idle_enter <-do_idle
<idle>-0 [007] d..1. 231.448855: arch_cpu_idle_enter <-do_idle
<idle>-0 [007] d..1. 231.448855: tsc_verify_tsc_adjust <-arch_cpu_idle_enter
<idle>-0 [002] d..1. 231.448855: tsc_verify_tsc_adjust <-arch_cpu_idle_enter
bash-1056 [001] d.... 231.448856: fpregs_assert_state_consistent <-arch_exit_to_user_mode_prepare
<idle>-0 [007] d..1. 231.448856: local_touch_nmi <-do_idle
<idle>-0 [002] d..1. 231.448856: local_touch_nmi <-do_idle
bash-1056 [001] d.... 231.448856: switch_fpu_return <-arch_exit_to_user_mode_prepare
<idle>-0 [007] d..1. 231.448856: rcu_nocb_flush_deferred_wakeup <-do_idle
<idle>-0 [002] d..1. 231.448856: rcu_nocb_flush_deferred_wakeup <-do_idle
<idle>-0 [007] d..1. 231.448857: cpuidle_get_cpu_driver <-do_idle
<idle>-0 [002] d..1. 231.448857: cpuidle_get_cpu_driver <-do_idle
<idle>-0 [007] d..1. 231.448857: cpuidle_not_available <-do_idle
[..]
Not too read only!
I change permissions all the time for tracefs files, so I don't want
that changed.
This is not the same as sysfs. Let's keep it simple. Have all the open
callers that can do writes return error -EACCES if a file allows writes
and is open for write, but is part of the read only instance.
-- Steve
^ permalink raw reply
* Re: [PATCH v8 3/6] tracefs: Check file permission even if user has CAP_DAC_OVERRIDE
From: Steven Rostedt @ 2026-02-11 15:46 UTC (permalink / raw)
To: Masami Hiramatsu (Google)
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
In-Reply-To: <177071303130.2293046.2400906233143699263.stgit@mhiramat.tok.corp.google.com>
On Tue, 10 Feb 2026 17:43:51 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:
> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
>
> Strictly checking the file read/write permission even if the owner has
> CAP_DAC_OVERRIDE on tracefs as same as sysfs.
> Tracefs is a pseudo filesystem, just like sysfs, so any file that the
> system defines as unwritable should actually be unwritable by anyone.
This is getting too complex and still doesn't work. As I said in my
other email, simply check for the trace_array being readonly on opens()
and return -EACCES if it is and was opened for write or read-write.
With this still not working this late in the game, it will need to wait
until the next merge window. I'll take the first two patches of this
series now though.
-- Steve
^ permalink raw reply
* Re: [PATCH v13 00/18] unwind_deferred: Implement sframe handling
From: Jens Remus @ 2026-02-11 16:15 UTC (permalink / raw)
To: Dylan Hatch
Cc: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
Steven Rostedt, Josh Poimboeuf, Masami Hiramatsu,
Mathieu Desnoyers, Peter Zijlstra, Ingo Molnar, Jiri Olsa,
Arnaldo Carvalho de Melo, Namhyung Kim, Thomas Gleixner,
Andrii Nakryiko, Indu Bhagat, Jose E. Marchesi, Beau Belgrave,
Linus Torvalds, Andrew Morton, Florian Weimer, Kees Cook,
Carlos O'Donell, Sam James, Borislav Petkov, Dave Hansen,
David Hildenbrand, H. Peter Anvin, Liam R. Howlett,
Lorenzo Stoakes, Michal Hocko, Mike Rapoport, Suren Baghdasaryan,
Vlastimil Babka, Heiko Carstens, Vasily Gorbik
In-Reply-To: <CADBMgpyHw_kgb+Fc+h+Z3ytwMBwDG9B=yai=7g4UWP6AErE77w@mail.gmail.com>
On 2/11/2026 2:47 AM, Dylan Hatch wrote:
> On Tue, Jan 27, 2026 at 7:06 AM Jens Remus <jremus@linux.ibm.com> wrote:
>>
>> This is the implementation of parsing the SFrame V3 stack trace information
>> from an .sframe section in an ELF file. It's a continuation of Josh's and
>> Steve's work that can be found here:
>>
>> https://lore.kernel.org/all/cover.1737511963.git.jpoimboe@kernel.org/
>> https://lore.kernel.org/all/20250827201548.448472904@kernel.org/
>>
>> Currently the only way to get a user space stack trace from a stack
>> walk (and not just copying large amount of user stack into the kernel
>> ring buffer) is to use frame pointers. This has a few issues. The biggest
>> one is that compiling frame pointers into every application and library
>> has been shown to cause performance overhead.
>>
>> Another issue is that the format of the frames may not always be consistent
>> between different compilers and some architectures (s390) has no defined
>> format to do a reliable stack walk. The only way to perform user space
>> profiling on these architectures is to copy the user stack into the kernel
>> buffer.
>>
>> SFrame [1] is now supported in binutils (x86-64, ARM64, and s390). There is
>> discussions going on about supporting SFrame in LLVM. SFrame acts more like
>> ORC, and lives in the ELF executable file as its own section. Like ORC it
>> has two tables where the first table is sorted by instruction pointers (IP)
>> and using the current IP and finding it's entry in the first table, it will
>> take you to the second table which will tell you where the return address
>> of the current function is located and then you can use that address to
>> look it up in the first table to find the return address of that function,
>> and so on. This performs a user space stack walk.
>>
>> Now because the .sframe section lives in the ELF file it needs to be faulted
>> into memory when it is used. This means that walking the user space stack
>> requires being in a faultable context. As profilers like perf request a stack
>> trace in interrupt or NMI context, it cannot do the walking when it is
>> requested. Instead it must be deferred until it is safe to fault in user
>> space. One place this is known to be safe is when the task is about to return
>> back to user space.
>>
>> This series makes the deferred unwind user code implement SFrame format V3
>> and enables it on x86-64.
>>
>> [1]: https://sourceware.org/binutils/wiki/sframe
>>
>>
>> This series applies on top of the tip perf/core branch:
>>
>> git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
>>
>> The to be stack-traced user space programs (and libraries) need to be
>> built with the recent SFrame stack trace information format V3, as
>> generated by the upcoming binutils 2.46 with assembler option --gsframe.
>> It can be built from source from the binutils-2_46-branch branch:
>>
>> git://sourceware.org/git/binutils-gdb.git binutils-2_46-branch
> Do you by chance have this work uploaded in a public branch somewhere?
> I'd like to get a new version of the SFrame for reliable stacktrace on
> arm64 patch series [1] working for SFrame V3, ideally with the SFrame
> library in your patch series here.
>
> https://lore.kernel.org/lkml/20250904223850.884188-1-dylanbhatch@google.com/
No, I don't. Following is how you can easily get to tip:perf/core with
this work applied using b4:
$ git checkout -b sframe v6.18
$ git pull --no-rebase git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core # pre-req for [PATCH v13 00/18] unwind_deferred: Implement sframe handling
$ b4 shazam -T 20260127150554.2760964-1-jremus@linux.ibm.com # [PATCH v13 00/18] unwind_deferred: Implement sframe handling
Following is how you can get to a tervolds:master with all of the latest
sframe related series on top using b4:
$ git fetch git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master:sframe
$ git checkout sframe
$ b4 shazam -T 20260127150554.2760964-1-jremus@linux.ibm.com # [PATCH v13 00/18] unwind_deferred: Implement sframe handling
$ git am -3 # resolve "unwind_user/sframe: Store .sframe section data in per-mm maple tree"
$ git am -3 # partially resolve "unwind_user/sframe: Add prctl() interface for registering .sframe sections"
$ git mergetool # manually resolve prctl.h and kernel/sys.c conflicts; bump PR_ADD_SFRAME and PR_REMOVE_SFRAME; each case must end with break;
$ git am --continue
$ b4 shazam -T 20260211141357.271402-1-jremus@linux.ibm.com # optional [PATCH v9 0/6] x86/vdso: VDSO updates and fixes for sframes
$ b4 shazam -T 20260127151926.2805123-1-jremus@linux.ibm.com # optional [PATCH v4 00/12] s390: SFrame user space unwinding
$ git am -3 # partially resolve "s390/vdso: Enable SFrame V3 generation in vDSO"
$ git mergetool # manually resolve arch/s390/kernel/vdso/Makefile conflict
$ git am --continue
$ git am -3 # resolve "s390/ptrace: Convert function macros to inline functions"
Regards,
Jens
--
Jens Remus
Linux on Z Development (D3303)
jremus@de.ibm.com / jremus@linux.ibm.com
IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Ehningen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/
^ permalink raw reply
* Re: [PATCH 1/5] tracing: Fix checking of freed trace_event_file for hist files
From: Steven Rostedt @ 2026-02-11 16:28 UTC (permalink / raw)
To: kernel test robot
Cc: Petr Pavlu, Masami Hiramatsu, oe-kbuild-all, Mathieu Desnoyers,
Tom Zanussi, linux-kernel, linux-trace-kernel
In-Reply-To: <202602110125.71oIfNm0-lkp@intel.com>
On Wed, 11 Feb 2026 01:40:48 +0800
kernel test robot <lkp@intel.com> wrote:
> url: https://github.com/intel-lab-lkp/linux/commits/Petr-Pavlu/tracing-Fix-checking-of-freed-trace_event_file-for-hist-files/20260210-194023
> base: 05f7e89ab9731565d8a62e3b5d1ec206485eeb0b
> patch link: https://lore.kernel.org/r/20260210113427.1068932-2-petr.pavlu%40suse.com
> patch subject: [PATCH 1/5] tracing: Fix checking of freed trace_event_file for hist files
> config: x86_64-buildonly-randconfig-004-20260210 (https://download.01.org/0day-ci/archive/20260211/202602110125.71oIfNm0-lkp@intel.com/config)
CONFIG_FTRACE is not set, and histograms have this as a dependency.
> compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260211/202602110125.71oIfNm0-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202602110125.71oIfNm0-lkp@intel.com/
>
> All errors (new ones prefixed by >>):
>
> kernel/trace/trace_events.c: In function 'remove_event_file_dir':
> >> kernel/trace/trace_events.c:1300:9: error: implicit declaration of function 'hist_poll_wakeup' [-Wimplicit-function-declaration]
> 1300 | hist_poll_wakeup();
> | ^~~~~~~~~~~~~~~~
>
This needs:
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 0a2b8229b999..8c627524c1d4 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -683,6 +683,8 @@ static inline void hist_poll_wakeup(void)
#define hist_poll_wait(file, wait) \
poll_wait(file, &hist_poll_wq, wait)
+#else
+# define hist_poll_wait(file, wait) do{ } while (0)
#endif
#define __TRACE_EVENT_FLAGS(name, value) \
-- Steve
^ permalink raw reply related
* Re: [PATCH 2/5] tracing: Fix checking of freed trace_event_file for id files
From: Steven Rostedt @ 2026-02-11 16:37 UTC (permalink / raw)
To: Petr Pavlu
Cc: Masami Hiramatsu, Mathieu Desnoyers, Tom Zanussi, linux-kernel,
linux-trace-kernel
In-Reply-To: <20260210113427.1068932-3-petr.pavlu@suse.com>
On Tue, 10 Feb 2026 12:28:17 +0100
Petr Pavlu <petr.pavlu@suse.com> wrote:
> The code for reading an event id currently uses file->f_inode->i_private to
> store the value of trace_event_file->event_call->event.type, unlike all
> other event files which use it to store a pointer to the associated
> trace_event_file data. The event_id_read() function retrieves this id value
> from i_private and checks if it is non-0/NULL to determine whether the
> event is still valid. This approach worked in the past when
> remove_event_file_dir() would set i_private to NULL for all files in an
> event directory upon removal. However, with the introduction of eventfs,
> i_private is assigned when an eventfs inode is allocated and remains set
> throughout its lifetime. As a result, event_id_read() may fail to detect
> that an event is being removed.
Who cares? It's just an id. If the event is being removed, there's
nothing wrong with still returning its id. The code currently is very
simple, I don't want to make it complex for something nobody cares
about.
-- Steve
>
> Fix this issue by changing the event id file to use i_private to store
> a trace_event_file pointer and utilize event_file_file() to check for the
> EVENT_FILE_FL_FREED flag.
^ permalink raw reply
* Re: [PATCH 4/5] tracing: Clean up access to trace_event_file from a file pointer
From: Steven Rostedt @ 2026-02-11 16:45 UTC (permalink / raw)
To: Petr Pavlu
Cc: Masami Hiramatsu, Mathieu Desnoyers, Tom Zanussi, linux-kernel,
linux-trace-kernel
In-Reply-To: <20260210113427.1068932-5-petr.pavlu@suse.com>
On Tue, 10 Feb 2026 12:28:19 +0100
Petr Pavlu <petr.pavlu@suse.com> wrote:
> In the past, when removing an event directory in remove_event_file_dir(),
> the code set i_private to NULL for all event files and readers were
> expected to check for this state to recognize that the event is being
> removed. In the case of event_id_read(), the value was read using
> event_file_data() without acquiring the event_mutex. This required
> event_file_data() to use READ_ONCE() when retrieving the i_private data.
I'm OK with this change. Instead of removing the event_file_data() like
you did from event_id_read(), just open code it there. The id is
simple, let's keep it that way.
That is, something like:
int id = (long)READ_ONCE(file_inode(filp)->i_private);
Feel free to add comments to explain it.
Thanks,
-- Steve
^ permalink raw reply
* Re: [PATCH] tracing: make tr->d_max_latency accessible without CONFIG_FSNOTIFY
From: Steven Rostedt @ 2026-02-11 17:51 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Masami Hiramatsu, Arnd Bergmann, Mathieu Desnoyers, Tom Zanussi,
pengdonglin, Shengming Hu, linux-kernel, linux-trace-kernel
In-Reply-To: <20260210141310.1605322-1-arnd@kernel.org>
On Tue, 10 Feb 2026 15:13:06 +0100
Arnd Bergmann <arnd@kernel.org> wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> A recent change attempted to make the tracing_max_latency file visible
> unconditionally, but this lead to a build failure:
>
> kernel/trace/trace.c: In function 'trace_create_maxlat_file':
> kernel/trace/trace.c:1543:13: error: 'struct trace_array' has no member named 'd_max_latency'; did you mean 'max_latency'?
> 1543 | tr->d_max_latency = trace_create_file("tracing_max_latency",
> | ^~~~~~~~~~~~~
>
> Make the corresponding change in the header file.
>
> Fixes: ba73713da50e ("tracing: Clean up use of trace_create_maxlat_file()")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Beat you to it ;-)
https://lore.kernel.org/linux-trace-kernel/20260209194631.788bfc85@fedora/
-- Steve
^ permalink raw reply
* Re: [PATCH] tracing: make tr->d_max_latency accessible without CONFIG_FSNOTIFY
From: Steven Rostedt @ 2026-02-11 18:15 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Masami Hiramatsu, Arnd Bergmann, Mathieu Desnoyers, Tom Zanussi,
pengdonglin, Shengming Hu, linux-kernel, linux-trace-kernel
In-Reply-To: <20260211125152.3afe6e4f@fedora>
On Wed, 11 Feb 2026 12:51:52 -0500
Steven Rostedt <rostedt@goodmis.org> wrote:
> On Tue, 10 Feb 2026 15:13:06 +0100
> Arnd Bergmann <arnd@kernel.org> wrote:
>
> > From: Arnd Bergmann <arnd@arndb.de>
> >
> > A recent change attempted to make the tracing_max_latency file visible
> > unconditionally, but this lead to a build failure:
> >
> > kernel/trace/trace.c: In function 'trace_create_maxlat_file':
> > kernel/trace/trace.c:1543:13: error: 'struct trace_array' has no member named 'd_max_latency'; did you mean 'max_latency'?
> > 1543 | tr->d_max_latency = trace_create_file("tracing_max_latency",
> > | ^~~~~~~~~~~~~
> >
> > Make the corresponding change in the header file.
> >
> > Fixes: ba73713da50e ("tracing: Clean up use of trace_create_maxlat_file()")
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>
> Beat you to it ;-)
>
> https://lore.kernel.org/linux-trace-kernel/20260209194631.788bfc85@fedora/
In fact, our changes were so identical that patchwork set both my patch
and your patch to queued when I applied mine to linux-next!
https://patchwork.kernel.org/project/linux-trace-kernel/patch/20260210141310.1605322-1-arnd@kernel.org/
-- Steve
^ permalink raw reply
* Re: [PATCH v6 1/4] tracing: Reset last_boot_info if ring buffer is reset
From: Steven Rostedt @ 2026-02-11 18:28 UTC (permalink / raw)
To: Masami Hiramatsu (Google)
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
In-Reply-To: <20260206225051.f22b670b54e8906a4bc1bec9@kernel.org>
On Fri, 6 Feb 2026 22:50:51 +0900
Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:
> On Wed, 4 Feb 2026 20:40:49 -0500
> Steven Rostedt <rostedt@goodmis.org> wrote:
>
> > On Sun, 1 Feb 2026 12:29:07 +0900
> > "Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:
> >
> > > @@ -8036,6 +8042,7 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
> > > tracing_reset_online_cpus(&tr->max_buffer);
> > > else
> > > tracing_reset_cpu(&tr->max_buffer, iter->cpu_file);
> > > + update_last_data_if_empty(tr);
> >
> > Is this needed? Memory mapped buffers (which the persistent ring buffer
> > is) do not have snapshot buffers.
>
> Yeah, I did this just for consistency. But it is better to just leave
> the comment here.
>
I have code to move all the snapshot buffers into its own file. I'm
going to drop this one as I think leaving it makes it more confusing.
-- Steve
^ permalink raw reply
* Re: [PATCH v6 1/4] tracing: Reset last_boot_info if ring buffer is reset
From: Steven Rostedt @ 2026-02-11 18:33 UTC (permalink / raw)
To: Masami Hiramatsu (Google)
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
In-Reply-To: <20260211132848.2bda172a@fedora>
On Wed, 11 Feb 2026 13:28:48 -0500
Steven Rostedt <rostedt@goodmis.org> wrote:
> I have code to move all the snapshot buffers into its own file. I'm
> going to drop this one as I think leaving it makes it more confusing.
Never mind, I was looking at the wrong patch.
-- Steve
^ permalink raw reply
* [PATCH V4] blktrace: log dropped REQ_OP_ZONE_XXX events ver1
From: Chaitanya Kulkarni @ 2026-02-11 20:47 UTC (permalink / raw)
To: axboe, dlemoal
Cc: rostedt, mhiramat, linux-block, linux-trace-kernel,
Chaitanya Kulkarni
Add informational messages during blktrace setup when version 1 tools
are used on kernels with CONFIG_BLK_DEV_ZONED enabled. This alerts users
that REQ_OP_ZONE_* events will be dropped and suggests upgrading to
blktrace tools version 2 or later.
The warning is printed once during trace setup to inform users about
the limitation without spamming the logs during tracing operations.
Version 2 blktrace tools properly handle zone management operations
(zone reset, zone open, zone close, zone finish, zone append) that
were added for zoned block devices.
* With old blktrace tool and this patch :-
blktests (master) # ./check blktrace/
blktrace/001 (blktrace zone management command tracing) [passed]
runtime 3.706s ... 3.735s
blktrace/002 (blktrace ftrace corruption with sysfs trace) [passed]
runtime 0.479s ... 0.456s
blktests (master) # dmesg -c
[ 9455.610899] null_blk: disk nullb0 created
[ 9455.610916] null_blk: module loaded
[ 9455.634103] run blktests blktrace/001 at 2026-02-02 15:02:23
[ 9455.651710] null_blk: nullb1: using native zone append
[ 9455.662852] null_blk: disk nullb1 created
*[ 9455.714998] blktrace: nullb1: blktrace events for zone operations will be dropped*
*[ 9455.715065] blktrace: use blktrace tools version >= 2 to track zone operations*
[ 9459.480181] null_blk: disk nullb0 created
[ 9459.480199] null_blk: module loaded
[ 9459.514464] run blktests blktrace/002 at 2026-02-02 15:02:27
[ 9459.541772] null_blk: disk nullb1 created
blktests (master) #
* With new blktrace tools and this patch :-
blktests (master) # ./check blktrace/
blktrace/001 (blktrace zone management command tracing) [passed]
runtime 3.735s ... 3.734s
blktrace/002 (blktrace ftrace corruption with sysfs trace) [passed]
runtime 0.456s ... 0.496s
blktests (master) # dmesg -c
[ 9490.395572] null_blk: disk nullb0 created
[ 9490.395591] null_blk: module loaded
[ 9490.419467] run blktests blktrace/001 at 2026-02-02 15:02:58
[ 9490.436416] null_blk: nullb1: using native zone append
[ 9490.447806] null_blk: disk nullb1 created
[ 9494.262176] null_blk: disk nullb0 created
[ 9494.262195] null_blk: module loaded
[ 9494.296653] run blktests blktrace/002 at 2026-02-02 15:03:02
[ 9494.322261] null_blk: disk nullb1 created
blktests (master) #
This helps users understand why zone operation traces may be missing
when using older blktrace tool versions with modern kernels that
support REQ_OP_ZONE_XXX in blktrace.
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Chaitanya Kulkarni <kch@nvidia.com>
---
V3->V4:-
Replace REQ_OP_ZONE_XXX with "zone operations". (Damien, Jens)
---
kernel/trace/blktrace.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index d031c8d80be4..04b41c698127 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -741,6 +741,12 @@ static void blk_trace_setup_finalize(struct request_queue *q,
* to underscores for this to work as expected
*/
strreplace(buts->name, '/', '_');
+ if (version == 1 && IS_ENABLED(CONFIG_BLK_DEV_ZONED)) {
+ pr_info("%s: blktrace events for zone operations will be dropped\n",
+ name);
+ pr_info("use blktrace tools version >= 2 to track zone operations\n");
+
+ }
bt->version = version;
bt->act_mask = buts->act_mask;
--
2.39.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox