* Re: [PATCH] tracing: Remove redundant call to event_trigger_reset_filter() in event_hist_trigger_parse()
From: Masami Hiramatsu @ 2026-01-08 23:53 UTC (permalink / raw)
To: Steven Rostedt
Cc: LKML, Linux Trace Kernel, Masami Hiramatsu, Mathieu Desnoyers,
Miaoqian Lin
In-Reply-To: <20260108174429.2d9ca51f@gandalf.local.home>
On Thu, 8 Jan 2026 17:44:29 -0500
Steven Rostedt <rostedt@kernel.org> wrote:
> From: Steven Rostedt <rostedt@goodmis.org>
>
> With the change to replace kfree() with trigger_data_free(), which starts
> out doing the exact same thing as event_trigger_reset_filter(), there's no
> reason to call event_trigger_reset_filter() before calling
> trigger_data_free(). Remove the call to it.
>
> Link: https://lore.kernel.org/linux-trace-kernel/20251211204520.0f3ba6d1@fedora/
>
Looks good to me.
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Thanks,
> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
> ---
> kernel/trace/trace_events_hist.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
> index f9886fff7123..4a7f945e368d 100644
> --- a/kernel/trace/trace_events_hist.c
> +++ b/kernel/trace/trace_events_hist.c
> @@ -6898,8 +6898,6 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
> out_unreg:
> event_trigger_unregister(cmd_ops, file, glob+1, trigger_data);
> out_free:
> - event_trigger_reset_filter(cmd_ops, trigger_data);
> -
> remove_hist_vars(hist_data);
>
> trigger_data_free(trigger_data);
> --
> 2.51.0
>
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply
* [PATCH v5] tracing: Guard __DECLARE_TRACE() use of __DO_TRACE_CALL() with SRCU-fast
From: Steven Rostedt @ 2026-01-09 3:05 UTC (permalink / raw)
To: LKML, Linux trace kernel, bpf
Cc: Masami Hiramatsu, Mathieu Desnoyers, Paul E. McKenney,
Sebastian Andrzej Siewior
From: "Paul E. McKenney" <paulmck@kernel.org>
The current use of guard(preempt_notrace)() within __DECLARE_TRACE()
to protect invocation of __DO_TRACE_CALL() means that BPF programs
attached to tracepoints are non-preemptible. This is unhelpful in
real-time systems, whose users apparently wish to use BPF while also
achieving low latencies. (Who knew?)
One option would be to use preemptible RCU, but this introduces
many opportunities for infinite recursion, which many consider to
be counterproductive, especially given the relatively small stacks
provided by the Linux kernel. These opportunities could be shut down
by sufficiently energetic duplication of code, but this sort of thing
is considered impolite in some circles.
Therefore, use the shiny new SRCU-fast API, which provides somewhat faster
readers than those of preemptible RCU, at least on Paul E. McKenney's
laptop, where task_struct access is more expensive than access to per-CPU
variables. And SRCU-fast provides way faster readers than does SRCU,
courtesy of being able to avoid the read-side use of smp_mb(). Also,
it is quite straightforward to create srcu_read_{,un}lock_fast_notrace()
functions.
While in the area, SRCU now supports early boot call_srcu(). Therefore,
remove the checks that used to avoid such use from rcu_free_old_probes()
before this commit was applied:
e53244e2c893 ("tracepoint: Remove SRCU protection")
The current commit can be thought of as an approximate revert of that
commit, with some compensating additions of preemption disabling.
This preemption disabling uses guard(preempt_notrace)().
However, Yonghong Song points out that BPF assumes that non-sleepable
BPF programs will remain on the same CPU, which means that migration
must be disabled whenever preemption remains enabled. In addition,
non-RT kernels have performance expectations that would be violated by
allowing the BPF programs to be preempted.
Therefore, continue to disable preemption in non-RT kernels, and protect
the BPF program with both SRCU and migration disabling for RT kernels,
and even then only if preemption is not already disabled.
Link: https://lore.kernel.org/all/20250613152218.1924093-1-bigeasy@linutronix.de/
Co-developed-by: Steve Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
Changes since v4: https://lore.kernel.org/all/20251216120819.3499e00e@gandalf.local.home/
- Added kerneldoc to trace_event_buffer_reserve{_syscall}
- Restructured the tracepoint.c code to not have #ifdef within functions
include/linux/trace_events.h | 24 ++++++++++++++
include/linux/tracepoint.h | 25 ++++++++++++--
include/trace/perf.h | 4 +--
include/trace/trace_events.h | 21 ++++++++++--
kernel/trace/trace_events.c | 61 +++++++++++++++++++++++++++++------
kernel/trace/trace_syscalls.c | 4 +--
kernel/tracepoint.c | 44 +++++++++++++++++++++++++
7 files changed, 164 insertions(+), 19 deletions(-)
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 3690221ba3d8..a2704c35eda8 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -222,6 +222,26 @@ static inline unsigned int tracing_gen_ctx_dec(void)
return trace_ctx;
}
+/*
+ * When PREEMPT_RT is enabled, trace events are called with disabled
+ * migration. The trace events need to know if the tracepoint disabled
+ * migration or not so that what is recorded to the ring buffer shows
+ * the state of when the trace event triggered, and not the state caused
+ * by the trace event.
+ */
+#ifdef CONFIG_PREEMPT_RT
+static inline unsigned int tracing_gen_ctx_dec_cond(void)
+{
+ unsigned int trace_ctx;
+
+ trace_ctx = tracing_gen_ctx_dec();
+ /* The migration counter starts at bit 4 */
+ return trace_ctx - (1 << 4);
+}
+#else
+# define tracing_gen_ctx_dec_cond() tracing_gen_ctx_dec()
+#endif
+
struct trace_event_file;
struct ring_buffer_event *
@@ -313,6 +333,10 @@ void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer,
struct trace_event_file *trace_file,
unsigned long len);
+void *trace_event_buffer_reserve_syscall(struct trace_event_buffer *fbuffer,
+ struct trace_event_file *trace_file,
+ unsigned long len);
+
void trace_event_buffer_commit(struct trace_event_buffer *fbuffer);
enum {
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 8a56f3278b1b..0563c7d9fcb2 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -100,6 +100,25 @@ void for_each_tracepoint_in_module(struct module *mod,
}
#endif /* CONFIG_MODULES */
+/*
+ * BPF programs can attach to the tracepoint callbacks. But if the
+ * callbacks are called with preemption disabled, the BPF programs
+ * can cause quite a bit of latency. When PREEMPT_RT is enabled,
+ * instead of disabling preemption, use srcu_fast_notrace() for
+ * synchronization. As BPF programs that are attached to tracepoints
+ * expect to stay on the same CPU, also disable migration.
+ */
+#ifdef CONFIG_PREEMPT_RT
+extern struct srcu_struct tracepoint_srcu;
+# define tracepoint_sync() synchronize_srcu(&tracepoint_srcu);
+# define tracepoint_guard() \
+ guard(srcu_fast_notrace)(&tracepoint_srcu); \
+ guard(migrate)()
+#else
+# define tracepoint_sync() synchronize_rcu();
+# define tracepoint_guard() guard(preempt_notrace)()
+#endif
+
/*
* tracepoint_synchronize_unregister must be called between the last tracepoint
* probe unregistration and the end of module exit to make sure there is no
@@ -115,7 +134,7 @@ void for_each_tracepoint_in_module(struct module *mod,
static inline void tracepoint_synchronize_unregister(void)
{
synchronize_rcu_tasks_trace();
- synchronize_rcu();
+ tracepoint_sync();
}
static inline bool tracepoint_is_faultable(struct tracepoint *tp)
{
@@ -275,13 +294,13 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
return static_branch_unlikely(&__tracepoint_##name.key);\
}
-#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
+#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto)) \
static inline void __do_trace_##name(proto) \
{ \
TRACEPOINT_CHECK(name) \
if (cond) { \
- guard(preempt_notrace)(); \
+ tracepoint_guard(); \
__DO_TRACE_CALL(name, TP_ARGS(args)); \
} \
} \
diff --git a/include/trace/perf.h b/include/trace/perf.h
index a1754b73a8f5..348ad1d9b556 100644
--- a/include/trace/perf.h
+++ b/include/trace/perf.h
@@ -71,6 +71,7 @@ perf_trace_##call(void *__data, proto) \
u64 __count __attribute__((unused)); \
struct task_struct *__task __attribute__((unused)); \
\
+ guard(preempt_notrace)(); \
do_perf_trace_##call(__data, args); \
}
@@ -85,9 +86,8 @@ perf_trace_##call(void *__data, proto) \
struct task_struct *__task __attribute__((unused)); \
\
might_fault(); \
- preempt_disable_notrace(); \
+ guard(preempt_notrace)(); \
do_perf_trace_##call(__data, args); \
- preempt_enable_notrace(); \
}
/*
diff --git a/include/trace/trace_events.h b/include/trace/trace_events.h
index 4f22136fd465..6fb58387e9f1 100644
--- a/include/trace/trace_events.h
+++ b/include/trace/trace_events.h
@@ -429,6 +429,22 @@ do_trace_event_raw_event_##call(void *__data, proto) \
trace_event_buffer_commit(&fbuffer); \
}
+/*
+ * When PREEMPT_RT is enabled, the tracepoint does not disable preemption
+ * but instead disables migration. The callbacks for the trace events
+ * need to have a consistent state so that it can reflect the proper
+ * preempt_disabled counter.
+ */
+#ifdef CONFIG_PREEMPT_RT
+/* disable preemption for RT so that the counters still match */
+# define trace_event_guard() guard(preempt_notrace)()
+/* Have syscalls up the migrate disable counter to emulate non-syscalls */
+# define trace_syscall_event_guard() guard(migrate)()
+#else
+# define trace_event_guard()
+# define trace_syscall_event_guard()
+#endif
+
#undef DECLARE_EVENT_CLASS
#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
__DECLARE_EVENT_CLASS(call, PARAMS(proto), PARAMS(args), PARAMS(tstruct), \
@@ -436,6 +452,7 @@ __DECLARE_EVENT_CLASS(call, PARAMS(proto), PARAMS(args), PARAMS(tstruct), \
static notrace void \
trace_event_raw_event_##call(void *__data, proto) \
{ \
+ trace_event_guard(); \
do_trace_event_raw_event_##call(__data, args); \
}
@@ -447,9 +464,9 @@ static notrace void \
trace_event_raw_event_##call(void *__data, proto) \
{ \
might_fault(); \
- preempt_disable_notrace(); \
+ trace_syscall_event_guard(); \
+ guard(preempt_notrace)(); \
do_trace_event_raw_event_##call(__data, args); \
- preempt_enable_notrace(); \
}
/*
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 137b4d9bb116..758c8a4ec7c2 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -649,9 +649,9 @@ bool trace_event_ignore_this_pid(struct trace_event_file *trace_file)
}
EXPORT_SYMBOL_GPL(trace_event_ignore_this_pid);
-void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer,
- struct trace_event_file *trace_file,
- unsigned long len)
+static __always_inline void *buffer_reserve(struct trace_event_buffer *fbuffer,
+ struct trace_event_file *trace_file,
+ unsigned long len)
{
struct trace_event_call *event_call = trace_file->event_call;
@@ -659,13 +659,6 @@ void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer,
trace_event_ignore_this_pid(trace_file))
return NULL;
- /*
- * If CONFIG_PREEMPTION is enabled, then the tracepoint itself disables
- * preemption (adding one to the preempt_count). Since we are
- * interested in the preempt_count at the time the tracepoint was
- * hit, we need to subtract one to offset the increment.
- */
- fbuffer->trace_ctx = tracing_gen_ctx_dec();
fbuffer->trace_file = trace_file;
fbuffer->event =
@@ -679,8 +672,56 @@ void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer,
fbuffer->entry = ring_buffer_event_data(fbuffer->event);
return fbuffer->entry;
}
+
+/**
+ * trace_event_buffer_reserve - reserve space on the ring buffer for an event
+ * @fbuffer: information about how to save the event
+ * @trace_file: the instance file descriptor for the event
+ * @len: The length of the event
+ *
+ * The @fbuffer has information about the ring buffer and data will
+ * be added to it to be used by the call to trace_event_buffer_commit().
+ * The @trace_file is the desrciptor with information about the status
+ * of the given event for a specific trace_array instance.
+ * The @len is the length of data to save for the event.
+ *
+ * Returns a pointer to the data on the ring buffer or NULL if the
+ * event was not reserved (event was filtered, too big, or the buffer
+ * simply was disabled for write).
+ */
+void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer,
+ struct trace_event_file *trace_file,
+ unsigned long len)
+{
+ fbuffer->trace_ctx = tracing_gen_ctx_dec_cond();
+ return buffer_reserve(fbuffer, trace_file, len);
+}
EXPORT_SYMBOL_GPL(trace_event_buffer_reserve);
+/**
+ * trace_event_buffer_reserve_syscall - reserve space for a syscall event
+ * @fbuffer: information about how to save the event
+ * @trace_file: the instance file descriptor for the event
+ * @len: The length of the event
+ *
+ * This behaves exactly the same as trace_event_buffer_reserve(), but
+ * needs to act slightly different for system call events when PREEMPT_RT
+ * is enabled. The way the preempt count and migration disabled are
+ * set is different than trace_event_buffer_reserve(), as normal events
+ * have migration disabled instead of preemption in PREEMPT_RT, system
+ * call events do not disable migrating but still disable preemption.
+ *
+ * Returns the same as trace_event_buffer_reserve().
+ */
+void *trace_event_buffer_reserve_syscall(struct trace_event_buffer *fbuffer,
+ struct trace_event_file *trace_file,
+ unsigned long len)
+{
+ fbuffer->trace_ctx = tracing_gen_ctx_dec();
+ return buffer_reserve(fbuffer, trace_file, len);
+}
+
+
int trace_event_reg(struct trace_event_call *call,
enum trace_reg type, void *data)
{
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index e96d0063cbcf..f330fd22ea78 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -909,7 +909,7 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
size += sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args;
- entry = trace_event_buffer_reserve(&fbuffer, trace_file, size);
+ entry = trace_event_buffer_reserve_syscall(&fbuffer, trace_file, size);
if (!entry)
return;
@@ -955,7 +955,7 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret)
if (!sys_data)
return;
- entry = trace_event_buffer_reserve(&fbuffer, trace_file, sizeof(*entry));
+ entry = trace_event_buffer_reserve_syscall(&fbuffer, trace_file, sizeof(*entry));
if (!entry)
return;
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 62719d2941c9..17e11d91d029 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -34,9 +34,32 @@ enum tp_transition_sync {
struct tp_transition_snapshot {
unsigned long rcu;
+ unsigned long srcu_gp;
bool ongoing;
};
+/* In PREEMPT_RT, SRCU is used to protect the tracepoint callbacks */
+#ifdef CONFIG_PREEMPT_RT
+DEFINE_SRCU_FAST(tracepoint_srcu);
+EXPORT_SYMBOL_GPL(tracepoint_srcu);
+static inline void start_rt_synchronize(struct tp_transition_snapshot *snapshot)
+{
+ snapshot->srcu_gp = start_poll_synchronize_srcu(&tracepoint_srcu);
+}
+static inline void poll_rt_synchronize(struct tp_transition_snapshot *snapshot)
+{
+ if (!poll_state_synchronize_srcu(&tracepoint_srcu, snapshot->srcu_gp))
+ synchronize_srcu(&tracepoint_srcu);
+}
+#else
+static inline void start_rt_synchronize(struct tp_transition_snapshot *snapshot)
+{
+}
+static inline void poll_rt_synchronize(struct tp_transition_snapshot *snapshot)
+{
+}
+#endif
+
/* Protected by tracepoints_mutex */
static struct tp_transition_snapshot tp_transition_snapshot[_NR_TP_TRANSITION_SYNC];
@@ -46,6 +69,7 @@ static void tp_rcu_get_state(enum tp_transition_sync sync)
/* Keep the latest get_state snapshot. */
snapshot->rcu = get_state_synchronize_rcu();
+ start_rt_synchronize(snapshot);
snapshot->ongoing = true;
}
@@ -56,6 +80,7 @@ static void tp_rcu_cond_sync(enum tp_transition_sync sync)
if (!snapshot->ongoing)
return;
cond_synchronize_rcu(snapshot->rcu);
+ poll_rt_synchronize(snapshot);
snapshot->ongoing = false;
}
@@ -101,10 +126,22 @@ static inline void *allocate_probes(int count)
return p == NULL ? NULL : p->probes;
}
+#ifdef CONFIG_PREEMPT_RT
+static void srcu_free_old_probes(struct rcu_head *head)
+{
+ kfree(container_of(head, struct tp_probes, rcu));
+}
+
+static void rcu_free_old_probes(struct rcu_head *head)
+{
+ call_srcu(&tracepoint_srcu, head, srcu_free_old_probes);
+}
+#else
static void rcu_free_old_probes(struct rcu_head *head)
{
kfree(container_of(head, struct tp_probes, rcu));
}
+#endif
static inline void release_probes(struct tracepoint *tp, struct tracepoint_func *old)
{
@@ -112,6 +149,13 @@ static inline void release_probes(struct tracepoint *tp, struct tracepoint_func
struct tp_probes *tp_probes = container_of(old,
struct tp_probes, probes[0]);
+ /*
+ * Tracepoint probes are protected by either RCU or
+ * Tasks Trace RCU and also by SRCU. By calling the SRCU
+ * callback in the [Tasks Trace] RCU callback we cover
+ * both cases. So let us chain the SRCU and [Tasks Trace]
+ * RCU callbacks to wait for both grace periods.
+ */
if (tracepoint_is_faultable(tp))
call_rcu_tasks_trace(&tp_probes->rcu, rcu_free_old_probes);
else
--
2.51.0
^ permalink raw reply related
* Re: [PATCH v2] selftests/tracing: Fix test_multiple_writes stall
From: Fushuai Wang @ 2026-01-09 3:27 UTC (permalink / raw)
To: rostedt
Cc: fushuai.wang, linux-kernel, linux-kselftest, linux-trace-kernel,
mathieu.desnoyers, mhiramat, shuah, skhan, wangfushuai
In-Reply-To: <20260108165247.3ae2f21a@gandalf.local.home>
> Anyway, Fushuai, you can add to the top of your commit:
>
> From: Fushuai Wang <wangfushuai@baidu.com>
>
> and that will make the From and SoB match without having to change your
> mail client. I usually have that. Because Linus doesn't like my patches
> having my company name in it for the "author" but I have it in the SoB to
> give credit to the one paying me to do the work.
Thanks!
I will send a v3 shortly.
---
Regards,
WANG
^ permalink raw reply
* [PATCH v2 2/3] Documentation: tracing: Add PCI controller event documentation
From: Shawn Lin @ 2026-01-09 3:29 UTC (permalink / raw)
To: Manivannan Sadhasivam, Bjorn Helgaas
Cc: linux-rockchip, linux-pci, linux-trace-kernel, linux-doc,
Steven Rostedt, Masami Hiramatsu, Shawn Lin
In-Reply-To: <1767929389-143957-1-git-send-email-shawn.lin@rock-chips.com>
The available tracepoint, pcie_ltssm_state_transition, monitors the LTSSM state
transistion for debugging purpose. Add description about it.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---
Changes in v2: None
Documentation/trace/events-pci-conotroller.rst | 41 ++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 Documentation/trace/events-pci-conotroller.rst
diff --git a/Documentation/trace/events-pci-conotroller.rst b/Documentation/trace/events-pci-conotroller.rst
new file mode 100644
index 0000000..8253d00
--- /dev/null
+++ b/Documentation/trace/events-pci-conotroller.rst
@@ -0,0 +1,41 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======================================
+Subsystem Trace Points: PCI Controller
+======================================
+
+Overview
+========
+The PCI controller tracing system provides tracepoints to monitor controller level
+information for debugging purpose. The events normally show up here:
+up here:
+
+ /sys/kernel/tracing/events/pci_controller
+
+Cf. include/trace/events/pci_controller.h for the events definitions.
+
+Available Tracepoints
+=====================
+
+pcie_ltssm_state_transition
+-----------------------
+
+Monitors PCIe LTSSM state transition including state and rate information
+::
+
+ pcie_ltssm_state_transition "dev: %s state: %s rate: %s\n"
+
+**Parameters**:
+
+* ``dev`` - PCIe root port name
+* ``state`` - PCIe LTSSM state
+* ``rate`` - PCIe bus speed
+
+**Example Usage**:
+
+ # Enable the tracepoint
+ echo 1 > /sys/kernel/debug/tracing/events/pci/pcie_ltssm_state_transition/enable
+
+ # Monitor events (the following output is generated when a device is linking)
+ cat /sys/kernel/debug/tracing/trace_pipe
+ kworker/0:0-9 [000] ..... 5.600221: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_EQ2 rate: 8.0 GT/s
--
2.7.4
^ permalink raw reply related
* [PATCH v2 0/3] PCI Controller event and LTSSM tracepoint support
From: Shawn Lin @ 2026-01-09 3:29 UTC (permalink / raw)
To: Manivannan Sadhasivam, Bjorn Helgaas
Cc: linux-rockchip, linux-pci, linux-trace-kernel, linux-doc,
Steven Rostedt, Masami Hiramatsu, 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.
Dependency
======
Need to apply on top of Mani's rework of error handling of dw_pcie_wait_for_link()
API in order to show the proper LTSSM name for dwc-based controller[1].
[1] https://lore.kernel.org/linux-pci/20260107-pci-dwc-suspend-rework-v4-0-9b5f3c72df0a@oss.qualcomm.com/T/#mfc5885b2afdeef4db1322597eaee61967558821e
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 v2:
- create PCI controller tracepoint instead of debugfs(Mani)
- Link to v1: https://lore.kernel.org/linux-pci/ym435w3ltwc7vln7g6j3ijswsarubwjazux65ttcqtrbr3i5fu@gig3qlzdkopf/T/#t
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-conotroller.rst | 41 ++++++++++++
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 92 ++++++++++++++++++++++++++
drivers/pci/trace.c | 1 +
include/trace/events/pci_controller.h | 44 ++++++++++++
4 files changed, 178 insertions(+)
create mode 100644 Documentation/trace/events-pci-conotroller.rst
create mode 100644 include/trace/events/pci_controller.h
--
2.7.4
^ permalink raw reply
* [PATCH v2 1/3] PCI: trace: Add PCI controller LTSSM transition tracepoint
From: Shawn Lin @ 2026-01-09 3:29 UTC (permalink / raw)
To: Manivannan Sadhasivam, Bjorn Helgaas
Cc: linux-rockchip, linux-pci, linux-trace-kernel, linux-doc,
Steven Rostedt, Masami Hiramatsu, Shawn Lin
In-Reply-To: <1767929389-143957-1-git-send-email-shawn.lin@rock-chips.com>
Some platforms may provide LTSSM trace functionality, recording historical
LTSSM state transition information. This is very useful for debugging, such
as when certain devices cannot be recognized or link broken during test.
Implement the pci controller tracepoint for recording LTSSM and rate.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---
Changes in v2: None
drivers/pci/trace.c | 1 +
include/trace/events/pci_controller.h | 44 +++++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
create mode 100644 include/trace/events/pci_controller.h
diff --git a/drivers/pci/trace.c b/drivers/pci/trace.c
index cf11abc..c1da9d3 100644
--- a/drivers/pci/trace.c
+++ b/drivers/pci/trace.c
@@ -9,3 +9,4 @@
#define CREATE_TRACE_POINTS
#include <trace/events/pci.h>
+#include <trace/events/pci_controller.h>
diff --git a/include/trace/events/pci_controller.h b/include/trace/events/pci_controller.h
new file mode 100644
index 0000000..47d54c6
--- /dev/null
+++ b/include/trace/events/pci_controller.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM pci_controller
+
+#if !defined(_TRACE_HW_EVENT_PCI_CONTROLLER_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_HW_EVENT_PCI_CONTROLLER_H
+
+#include <uapi/linux/pci_regs.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(pcie_ltssm_state_transition,
+ TP_PROTO(const char *dev_name, const char *state, u32 rate),
+ TP_ARGS(dev_name, state, rate),
+
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name)
+ __string(state, state)
+ __field(u32, rate)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev_name);
+ __assign_str(state);
+ __entry->rate = rate;
+ ),
+
+ TP_printk("dev: %s state: %s rate: %s",
+ __get_str(dev_name), __get_str(state),
+ __print_symbolic(__entry->rate,
+ { PCIE_SPEED_2_5GT, "2.5 GT/s" },
+ { PCIE_SPEED_5_0GT, "5.0 GT/s" },
+ { PCIE_SPEED_8_0GT, "8.0 GT/s" },
+ { PCIE_SPEED_16_0GT, "16.0 GT/s" },
+ { PCIE_SPEED_32_0GT, "32.0 GT/s" },
+ { PCIE_SPEED_64_0GT, "64.0 GT/s" },
+ { PCI_SPEED_UNKNOWN, "Unknown" }
+ )
+ )
+);
+
+#endif /* _TRACE_HW_EVENT_PCI_CONTROLLER_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
--
2.7.4
^ permalink raw reply related
* [PATCH v3] selftests/tracing: Fix test_multiple_writes stall
From: Fushuai Wang @ 2026-01-09 3:36 UTC (permalink / raw)
To: rostedt, mhiramat, mathieu.desnoyers, shuah, wangfushuai
Cc: skhan, linux-kernel, linux-trace-kernel, linux-kselftest
From: Fushuai Wang <wangfushuai@baidu.com>
When /sys/kernel/tracing/buffer_size_kb is less than 12KB,
the test_multiple_writes test will stall and wait for more
input due to insufficient buffer space.
Check current buffer_size_kb value before the test. If it is
less than 12KB, it temporarily increase the buffer to 12KB,
and restore the original value after the tests are completed.
Fixes: 37f46601383a ("selftests/tracing: Add basic test for trace_marker_raw file")
Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Fushuai Wang <wangfushuai@baidu.com>
Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
V2 -> V3: Make the From and SoB match.
V1 -> V2: Restore buffer_size_kb outside of awk script.
.../ftrace/test.d/00basic/trace_marker_raw.tc | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc
index 7daf7292209e..a2c42e13f614 100644
--- a/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc
+++ b/tools/testing/selftests/ftrace/test.d/00basic/trace_marker_raw.tc
@@ -89,6 +89,7 @@ test_buffer() {
# The id must be four bytes, test that 3 bytes fails a write
if echo -n abc > ./trace_marker_raw ; then
echo "Too small of write expected to fail but did not"
+ echo ${ORIG} > buffer_size_kb
exit_fail
fi
@@ -99,9 +100,24 @@ test_buffer() {
if write_buffer 0xdeadbeef $size ; then
echo "Too big of write expected to fail but did not"
+ echo ${ORIG} > buffer_size_kb
exit_fail
fi
}
+ORIG=`cat buffer_size_kb`
+
+# test_multiple_writes test needs at least 12KB buffer
+NEW_SIZE=12
+
+if [ ${ORIG} -lt ${NEW_SIZE} ]; then
+ echo ${NEW_SIZE} > buffer_size_kb
+fi
+
test_buffer
-test_multiple_writes
+if ! test_multiple_writes; then
+ echo ${ORIG} > buffer_size_kb
+ exit_fail
+fi
+
+echo ${ORIG} > buffer_size_kb
--
2.36.1
^ permalink raw reply related
* Re: [PATCH v2 1/3] PCI: trace: Add PCI controller LTSSM transition tracepoint
From: Steven Rostedt @ 2026-01-09 3:42 UTC (permalink / raw)
To: Shawn Lin
Cc: Manivannan Sadhasivam, Bjorn Helgaas, linux-rockchip, linux-pci,
linux-trace-kernel, linux-doc, Masami Hiramatsu
In-Reply-To: <1767929389-143957-2-git-send-email-shawn.lin@rock-chips.com>
On Fri, 9 Jan 2026 11:29:47 +0800
Shawn Lin <shawn.lin@rock-chips.com> wrote:
> + TP_printk("dev: %s state: %s rate: %s",
> + __get_str(dev_name), __get_str(state),
> + __print_symbolic(__entry->rate,
> + { PCIE_SPEED_2_5GT, "2.5 GT/s" },
> + { PCIE_SPEED_5_0GT, "5.0 GT/s" },
> + { PCIE_SPEED_8_0GT, "8.0 GT/s" },
> + { PCIE_SPEED_16_0GT, "16.0 GT/s" },
> + { PCIE_SPEED_32_0GT, "32.0 GT/s" },
> + { PCIE_SPEED_64_0GT, "64.0 GT/s" },
> + { PCI_SPEED_UNKNOWN, "Unknown" }
As these values are all enums, you may want to add in this file:
TRACE_DEFINE_ENUM(PCIE_SPEED_2_5GT);
TRACE_DEFINE_ENUM(PCIE_SPEED_5_0GT);
[..]
TRACE_DEFINE_ENUM(PCIE_SPEED_UNKNOWN);
So that this can be parsed by user space tooling such as trace-cmd and
perf.
-- Steve
> + )
> + )
> +);
> +
^ permalink raw reply
* Re: [PATCH v2 2/3] Documentation: tracing: Add PCI controller event documentation
From: Bagas Sanjaya @ 2026-01-09 3:53 UTC (permalink / raw)
To: Shawn Lin, Manivannan Sadhasivam, Bjorn Helgaas
Cc: linux-rockchip, linux-pci, linux-trace-kernel, linux-doc,
Steven Rostedt, Masami Hiramatsu
In-Reply-To: <1767929389-143957-3-git-send-email-shawn.lin@rock-chips.com>
[-- Attachment #1: Type: text/plain, Size: 938 bytes --]
On Fri, Jan 09, 2026 at 11:29:48AM +0800, Shawn Lin wrote:
> Documentation/trace/events-pci-conotroller.rst | 41 ++++++++++++++++++++++++++
Missing toctree entry in Documentation/trace/index.rst.
> +Available Tracepoints
> +=====================
> +
> +pcie_ltssm_state_transition
> +-----------------------
Please match section underline length.
> +**Example Usage**:
> +
> + # Enable the tracepoint
> + echo 1 > /sys/kernel/debug/tracing/events/pci/pcie_ltssm_state_transition/enable
> +
> + # Monitor events (the following output is generated when a device is linking)
> + cat /sys/kernel/debug/tracing/trace_pipe
> + kworker/0:0-9 [000] ..... 5.600221: pcie_ltssm_state_transition: dev: a40000000.pcie state: RCVRY_EQ2 rate: 8.0 GT/s
Wrap above example snippets in literal code block (use double colon).
Thanks.
--
An old man doll... just what I always wanted! - Clara
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/3] Documentation: tracing: Add PCI controller event documentation
From: Manivannan Sadhasivam @ 2026-01-09 5:19 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: <1767929389-143957-3-git-send-email-shawn.lin@rock-chips.com>
On Fri, Jan 09, 2026 at 11:29:48AM +0800, Shawn Lin wrote:
> The available tracepoint, pcie_ltssm_state_transition, monitors the LTSSM state
> transistion for debugging purpose. Add description about it.
>
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> ---
>
> Changes in v2: None
>
> Documentation/trace/events-pci-conotroller.rst | 41 ++++++++++++++++++++++++++
> 1 file changed, 41 insertions(+)
> create mode 100644 Documentation/trace/events-pci-conotroller.rst
>
> diff --git a/Documentation/trace/events-pci-conotroller.rst b/Documentation/trace/events-pci-conotroller.rst
> new file mode 100644
> index 0000000..8253d00
> --- /dev/null
> +++ b/Documentation/trace/events-pci-conotroller.rst
> @@ -0,0 +1,41 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +======================================
> +Subsystem Trace Points: PCI Controller
> +======================================
> +
> +Overview
> +========
> +The PCI controller tracing system provides tracepoints to monitor controller level
> +information for debugging purpose. The events normally show up here:
> +up here:
> +
> + /sys/kernel/tracing/events/pci_controller
> +
> +Cf. include/trace/events/pci_controller.h for the events definitions.
> +
> +Available Tracepoints
> +=====================
> +
> +pcie_ltssm_state_transition
> +-----------------------
> +
> +Monitors PCIe LTSSM state transition including state and rate information
> +::
> +
> + pcie_ltssm_state_transition "dev: %s state: %s rate: %s\n"
> +
> +**Parameters**:
> +
> +* ``dev`` - PCIe root port name
'PCIe controller instance'
> +* ``state`` - PCIe LTSSM state
> +* ``rate`` - PCIe bus speed
'PCIe data rate'
> +
> +**Example Usage**:
> +
> + # Enable the tracepoint
> + echo 1 > /sys/kernel/debug/tracing/events/pci/pcie_ltssm_state_transition/enable
/sys/kernel/debug/tracing/events/pci_controller/pcie_ltssm_state_transition/enable
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH v2 3/3] PCI: dw-rockchip: Add pcie_ltssm_state_transition trace support
From: Manivannan Sadhasivam @ 2026-01-09 5:55 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: <1767929389-143957-4-git-send-email-shawn.lin@rock-chips.com>
On Fri, Jan 09, 2026 at 11:29:49AM +0800, Shawn Lin wrote:
> Rockchip platforms provide a 64x4 bytes debug FIFO to trace the
> LTSSM history. Any LTSSM change will be recorded. It's userful
> for debug purpose, for example link failure, etc.
>
> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> ---
>
> Changes in v2:
> - use tracepoint
>
> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 92 +++++++++++++++++++++++++++
> 1 file changed, 92 insertions(+)
>
> diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> index 352f513..be9639aa 100644
> --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> @@ -22,6 +22,8 @@
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
> #include <linux/reset.h>
> +#include <linux/workqueue.h>
> +#include <trace/events/pci_controller.h>
>
> #include "../../pci.h"
> #include "pcie-designware.h"
> @@ -73,6 +75,18 @@
> #define PCIE_CLIENT_CDM_RASDES_TBA_L1_1 BIT(4)
> #define PCIE_CLIENT_CDM_RASDES_TBA_L1_2 BIT(5)
>
> +/* Debug FIFO information */
> +#define PCIE_CLIENT_DBG_FIFO_MODE_CON 0x310
> +#define PCIE_CLIENT_DBG_EN 0xffff0007
> +#define PCIE_CLIENT_DBG_DIS 0xffff0000
> +#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
> +#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
> +#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
> +#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
> +#define PCIE_CLIENT_DBG_TRANSITION_DATA 0xffff0000
> +#define PCIE_CLIENT_DBG_FIFO_STATUS 0x350
> +#define PCIE_DBG_LTSSM_HISTORY_CNT 64
> +
> /* Hot Reset Control Register */
> #define PCIE_CLIENT_HOT_RESET_CTRL 0x180
> #define PCIE_LTSSM_APP_DLY2_EN BIT(1)
> @@ -96,6 +110,7 @@ struct rockchip_pcie {
> struct irq_domain *irq_domain;
> const struct rockchip_pcie_of_data *data;
> bool supports_clkreq;
> + struct delayed_work trace_work;
> };
>
> struct rockchip_pcie_of_data {
> @@ -206,6 +221,79 @@ static enum dw_pcie_ltssm rockchip_pcie_get_ltssm(struct dw_pcie *pci)
> return rockchip_pcie_get_ltssm_reg(rockchip) & PCIE_LTSSM_STATUS_MASK;
> }
>
> +#ifdef CONFIG_TRACING
> +static void rockchip_pcie_ltssm_trace_work(struct work_struct *work)
> +{
> + struct rockchip_pcie *rockchip = container_of(work, struct rockchip_pcie,
> + trace_work.work);
> + struct dw_pcie *pci = &rockchip->pci;
> + enum dw_pcie_ltssm state;
> + u32 val, rate, l1ss, loop, prev_val = DW_PCIE_LTSSM_UNKNOWN;
Reverse Xmas order please.
> +
> + for (loop = 0; loop < PCIE_DBG_LTSSM_HISTORY_CNT; loop++) {
s/loop/i?
> + val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_DBG_FIFO_STATUS);
> + rate = (val & GENMASK(22, 20)) >> 20;
> + l1ss = (val & GENMASK(10, 8)) >> 8;
> + val &= PCIE_LTSSM_STATUS_MASK;
Can you use FIELD_ macros here?
> +
> + /* Two consecutive identical LTSSM means invalid subsequent data */
Interesting. Does the hardware maintain a counter to track the reads? So once
you break out of the loop and read it after 5s, you'll start from where you left
i.e., the duplicate entry or from the start of the counter again?
> + if ((loop > 0 && val == prev_val) || val > DW_PCIE_LTSSM_RCVRY_EQ3)
> + break;
> +
> + state = prev_val = val;
> + if (val == DW_PCIE_LTSSM_L1_IDLE) {
> + if (l1ss == 2)
> + state = DW_PCIE_LTSSM_L1_2;
> + else if (l1ss == 1)
> + state = DW_PCIE_LTSSM_L1_1;
I believe L1.0 is not supported.
> + }
> +
> + trace_pcie_ltssm_state_transition(dev_name(pci->dev),
> + dw_pcie_ltssm_status_string(state),
> + ((rate + 1) > pci->max_link_speed) ?
> + PCI_SPEED_UNKNOWN : PCIE_SPEED_2_5GT + rate);
> + }
> +
> + schedule_delayed_work(&rockchip->trace_work, msecs_to_jiffies(5000));
> +}
> +
> +static void rockchip_pcie_ltssm_trace(struct rockchip_pcie *rockchip,
> + bool en)
s/en/enable
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH v2 3/3] PCI: dw-rockchip: Add pcie_ltssm_state_transition trace support
From: Shawn Lin @ 2026-01-09 6:22 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: shawn.lin, Bjorn Helgaas, linux-rockchip, linux-pci,
linux-trace-kernel, linux-doc, Steven Rostedt, Masami Hiramatsu
In-Reply-To: <uev63wla4msmmhww4j3t2jim7lhvxjikvujwpxiblg5mz7jwwa@2jucxkbtcsfm>
在 2026/01/09 星期五 13:55, Manivannan Sadhasivam 写道:
> On Fri, Jan 09, 2026 at 11:29:49AM +0800, Shawn Lin wrote:
>> Rockchip platforms provide a 64x4 bytes debug FIFO to trace the
>> LTSSM history. Any LTSSM change will be recorded. It's userful
>> for debug purpose, for example link failure, etc.
>>
>> Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
>> ---
>>
>> Changes in v2:
>> - use tracepoint
>>
>> drivers/pci/controller/dwc/pcie-dw-rockchip.c | 92 +++++++++++++++++++++++++++
>> 1 file changed, 92 insertions(+)
>>
>> diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
>> index 352f513..be9639aa 100644
>> --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
>> +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
>> @@ -22,6 +22,8 @@
>> #include <linux/platform_device.h>
>> #include <linux/regmap.h>
>> #include <linux/reset.h>
>> +#include <linux/workqueue.h>
>> +#include <trace/events/pci_controller.h>
>>
>> #include "../../pci.h"
>> #include "pcie-designware.h"
>> @@ -73,6 +75,18 @@
>> #define PCIE_CLIENT_CDM_RASDES_TBA_L1_1 BIT(4)
>> #define PCIE_CLIENT_CDM_RASDES_TBA_L1_2 BIT(5)
>>
>> +/* Debug FIFO information */
>> +#define PCIE_CLIENT_DBG_FIFO_MODE_CON 0x310
>> +#define PCIE_CLIENT_DBG_EN 0xffff0007
>> +#define PCIE_CLIENT_DBG_DIS 0xffff0000
>> +#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
>> +#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
>> +#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
>> +#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
>> +#define PCIE_CLIENT_DBG_TRANSITION_DATA 0xffff0000
>> +#define PCIE_CLIENT_DBG_FIFO_STATUS 0x350
>> +#define PCIE_DBG_LTSSM_HISTORY_CNT 64
>> +
>> /* Hot Reset Control Register */
>> #define PCIE_CLIENT_HOT_RESET_CTRL 0x180
>> #define PCIE_LTSSM_APP_DLY2_EN BIT(1)
>> @@ -96,6 +110,7 @@ struct rockchip_pcie {
>> struct irq_domain *irq_domain;
>> const struct rockchip_pcie_of_data *data;
>> bool supports_clkreq;
>> + struct delayed_work trace_work;
>> };
>>
>> struct rockchip_pcie_of_data {
>> @@ -206,6 +221,79 @@ static enum dw_pcie_ltssm rockchip_pcie_get_ltssm(struct dw_pcie *pci)
>> return rockchip_pcie_get_ltssm_reg(rockchip) & PCIE_LTSSM_STATUS_MASK;
>> }
>>
>> +#ifdef CONFIG_TRACING
>> +static void rockchip_pcie_ltssm_trace_work(struct work_struct *work)
>> +{
>> + struct rockchip_pcie *rockchip = container_of(work, struct rockchip_pcie,
>> + trace_work.work);
>> + struct dw_pcie *pci = &rockchip->pci;
>> + enum dw_pcie_ltssm state;
>> + u32 val, rate, l1ss, loop, prev_val = DW_PCIE_LTSSM_UNKNOWN;
>
> Reverse Xmas order please.
>
>> +
>> + for (loop = 0; loop < PCIE_DBG_LTSSM_HISTORY_CNT; loop++) {
>
> s/loop/i?
>
>> + val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_DBG_FIFO_STATUS);
>> + rate = (val & GENMASK(22, 20)) >> 20;
>> + l1ss = (val & GENMASK(10, 8)) >> 8;
>> + val &= PCIE_LTSSM_STATUS_MASK;
>
> Can you use FIELD_ macros here?
>
>> +
>> + /* Two consecutive identical LTSSM means invalid subsequent data */
>
> Interesting. Does the hardware maintain a counter to track the reads? So once
> you break out of the loop and read it after 5s, you'll start from where you left
> i.e., the duplicate entry or from the start of the counter again?
>
Yes, the ring FIFO maintains counters for recording both of
last-read-point for user to continue to read, and last-valid-point for
HW to
continue to update transition state. So we could start from where we
left.
>> + if ((loop > 0 && val == prev_val) || val > DW_PCIE_LTSSM_RCVRY_EQ3)
>> + break;
>> +
>> + state = prev_val = val;
>> + if (val == DW_PCIE_LTSSM_L1_IDLE) {
>> + if (l1ss == 2)
>> + state = DW_PCIE_LTSSM_L1_2;
>> + else if (l1ss == 1)
>> + state = DW_PCIE_LTSSM_L1_1;
>
> I believe L1.0 is not supported.
>
I'm not sure I follow this comment. state is DW_PCIE_LTSSM_L1_IDLE
(L1.0) if l1ss is neither 1 nor 2.
>> + }
>> +
>> + trace_pcie_ltssm_state_transition(dev_name(pci->dev),
>> + dw_pcie_ltssm_status_string(state),
>> + ((rate + 1) > pci->max_link_speed) ?
>> + PCI_SPEED_UNKNOWN : PCIE_SPEED_2_5GT + rate);
>> + }
>> +
>> + schedule_delayed_work(&rockchip->trace_work, msecs_to_jiffies(5000));
>> +}
>> +
>> +static void rockchip_pcie_ltssm_trace(struct rockchip_pcie *rockchip,
>> + bool en)
>
> s/en/enable
>
> - Mani
>
^ permalink raw reply
* Re: [PATCH v2 3/3] PCI: dw-rockchip: Add pcie_ltssm_state_transition trace support
From: Manivannan Sadhasivam @ 2026-01-09 7:33 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: <dddbcb37-68d4-4ccb-9897-b1e5a4b41be7@rock-chips.com>
On Fri, Jan 09, 2026 at 02:22:10PM +0800, Shawn Lin wrote:
> 在 2026/01/09 星期五 13:55, Manivannan Sadhasivam 写道:
> > On Fri, Jan 09, 2026 at 11:29:49AM +0800, Shawn Lin wrote:
> > > Rockchip platforms provide a 64x4 bytes debug FIFO to trace the
> > > LTSSM history. Any LTSSM change will be recorded. It's userful
> > > for debug purpose, for example link failure, etc.
> > >
> > > Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> > > ---
> > >
> > > Changes in v2:
> > > - use tracepoint
> > >
> > > drivers/pci/controller/dwc/pcie-dw-rockchip.c | 92 +++++++++++++++++++++++++++
> > > 1 file changed, 92 insertions(+)
> > >
> > > diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> > > index 352f513..be9639aa 100644
> > > --- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> > > +++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
> > > @@ -22,6 +22,8 @@
> > > #include <linux/platform_device.h>
> > > #include <linux/regmap.h>
> > > #include <linux/reset.h>
> > > +#include <linux/workqueue.h>
> > > +#include <trace/events/pci_controller.h>
> > > #include "../../pci.h"
> > > #include "pcie-designware.h"
> > > @@ -73,6 +75,18 @@
> > > #define PCIE_CLIENT_CDM_RASDES_TBA_L1_1 BIT(4)
> > > #define PCIE_CLIENT_CDM_RASDES_TBA_L1_2 BIT(5)
> > > +/* Debug FIFO information */
> > > +#define PCIE_CLIENT_DBG_FIFO_MODE_CON 0x310
> > > +#define PCIE_CLIENT_DBG_EN 0xffff0007
> > > +#define PCIE_CLIENT_DBG_DIS 0xffff0000
> > > +#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
> > > +#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
> > > +#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
> > > +#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
> > > +#define PCIE_CLIENT_DBG_TRANSITION_DATA 0xffff0000
> > > +#define PCIE_CLIENT_DBG_FIFO_STATUS 0x350
> > > +#define PCIE_DBG_LTSSM_HISTORY_CNT 64
> > > +
> > > /* Hot Reset Control Register */
> > > #define PCIE_CLIENT_HOT_RESET_CTRL 0x180
> > > #define PCIE_LTSSM_APP_DLY2_EN BIT(1)
> > > @@ -96,6 +110,7 @@ struct rockchip_pcie {
> > > struct irq_domain *irq_domain;
> > > const struct rockchip_pcie_of_data *data;
> > > bool supports_clkreq;
> > > + struct delayed_work trace_work;
> > > };
> > > struct rockchip_pcie_of_data {
> > > @@ -206,6 +221,79 @@ static enum dw_pcie_ltssm rockchip_pcie_get_ltssm(struct dw_pcie *pci)
> > > return rockchip_pcie_get_ltssm_reg(rockchip) & PCIE_LTSSM_STATUS_MASK;
> > > }
> > > +#ifdef CONFIG_TRACING
> > > +static void rockchip_pcie_ltssm_trace_work(struct work_struct *work)
> > > +{
> > > + struct rockchip_pcie *rockchip = container_of(work, struct rockchip_pcie,
> > > + trace_work.work);
> > > + struct dw_pcie *pci = &rockchip->pci;
> > > + enum dw_pcie_ltssm state;
> > > + u32 val, rate, l1ss, loop, prev_val = DW_PCIE_LTSSM_UNKNOWN;
> >
> > Reverse Xmas order please.
> >
> > > +
> > > + for (loop = 0; loop < PCIE_DBG_LTSSM_HISTORY_CNT; loop++) {
> >
> > s/loop/i?
> >
> > > + val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_DBG_FIFO_STATUS);
> > > + rate = (val & GENMASK(22, 20)) >> 20;
> > > + l1ss = (val & GENMASK(10, 8)) >> 8;
> > > + val &= PCIE_LTSSM_STATUS_MASK;
> >
> > Can you use FIELD_ macros here?
> >
> > > +
> > > + /* Two consecutive identical LTSSM means invalid subsequent data */
> >
> > Interesting. Does the hardware maintain a counter to track the reads? So once
> > you break out of the loop and read it after 5s, you'll start from where you left
> > i.e., the duplicate entry or from the start of the counter again?
> >
>
> Yes, the ring FIFO maintains counters for recording both of last-read-point
> for user to continue to read, and last-valid-point for HW to
> continue to update transition state. So we could start from where we
> left.
>
Ok. Thanks for clarification. It'd be worth to add it to the existing comment.
> > > + if ((loop > 0 && val == prev_val) || val > DW_PCIE_LTSSM_RCVRY_EQ3)
> > > + break;
> > > +
> > > + state = prev_val = val;
> > > + if (val == DW_PCIE_LTSSM_L1_IDLE) {
> > > + if (l1ss == 2)
> > > + state = DW_PCIE_LTSSM_L1_2;
> > > + else if (l1ss == 1)
> > > + state = DW_PCIE_LTSSM_L1_1;
> >
> > I believe L1.0 is not supported.
> >
>
> I'm not sure I follow this comment. state is DW_PCIE_LTSSM_L1_IDLE
> (L1.0) if l1ss is neither 1 nor 2.
>
Ah ok. It was not clear that L1_IDLE is L1.0
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH] ring-buffer: Use a housekeeping CPU to wake up waiters
From: Petr Tesarik @ 2026-01-09 8:57 UTC (permalink / raw)
To: Steven Rostedt
Cc: Masami Hiramatsu, Mathieu Desnoyers, Sebastian Andrzej Siewior,
Clark Williams, linux-kernel, linux-trace-kernel, linux-rt-devel
In-Reply-To: <20260108115800.7a7fc8a7@gandalf.local.home>
On Thu, 8 Jan 2026 11:58:00 -0500
Steven Rostedt <rostedt@goodmis.org> wrote:
> On Thu, 8 Jan 2026 09:39:32 +0100
> Petr Tesarik <ptesarik@suse.com> wrote:
>
> > > > Or we simply change it to:
> > > >
> > > > static inline void
> > >
> > > Actually, the above should be noinline, as it's in a slower path, and
> > > should not be adding logic into the cache of the fast path.
> >
> > However, to be honest, I'm surprized this is considered slow path. My
> > use case is to record a few selected trace events with "trace-cmd
> > record", which spends most time polling trace_pipe_raw. Consequently,
> > there is almost always a pending waiter that requires a wakeup.
> >
> > In short, irq_work_queue() is the hot path for me.
> >
> > OTOH I don't mind making it noinline, because on recent Intel and AMD
> > systems, a function call (noinline) is often cheaper than an increase
> > in L1 cache footprint (caused by inlining). But I'm confused. I have
> > always thought most people use tracing same way as I do.
>
> The call to rb_wakeups() is a fast path, but the wakeup itself is a slow
> path. This is the case even when you have user space in a loop that is just
> waiting on data.
>
> User space tool:
>
> ring_buffer_wait() {
> wake_event_interruptible(.., rb_wait_cond(..));
> }
>
> Writer:
>
> rb_wakeups() {
> if (!full_hit())
> return;
> }
>
> The full_hit() is the watermark check. If you look at the tracefs
> directory, you'll see a "buffer_percent" file, which is default set to 50.
> That means that full_hit() will not return true until the ring buffer is
> around 50 percent full. This function is called thousands of times before
> the first wakeup happens.
>
> Let's look at even a waiter that isn't using the buffer percent. This means
> it will be woken up on any event in the buffer.
>
> rb_wakeups() {
> if (buffer->irq_work.waiters_pending) {
> buffer->irq_work.waiters_pending = false;
> /* irq_work_queue() supplies it's own memory barriers */
> irq_work_queue(&buffer->irq_work.work);
>
>
> So it clears the waiters_pending flag and wakes up the waiter. Now the
> waiter wakes up and starts reading the ring buffer. While the ring buffer
> has content, it will continue to read and doesn't block again until the
> ring buffer is empty. This means that thousands of events are being
> recorded with no waiters to wake up.
>
> See why this is a slow path?
Thank you for the detailed explanation. So, yeah, most people use it
differently from me, generating trace events fast enough that the
reader does not consume the previous event before the next one arrives.
I have removed both "inline" and "noinline" in v2, leaving it at the
discretion of the compiler. If you believe it deserves a "noinline",
feel free to add it. FWIW on x86-64, I didn't observe any measurable
diference either in latency or instruction cache footprint.
Petr T
^ permalink raw reply
* [PATCH v2 3/3] PCI: dw-rockchip: Add pcie_ltssm_state_transition trace support
From: Shawn Lin @ 2026-01-09 3:29 UTC (permalink / raw)
To: Manivannan Sadhasivam, Bjorn Helgaas
Cc: linux-rockchip, linux-pci, linux-trace-kernel, linux-doc,
Steven Rostedt, Masami Hiramatsu, Shawn Lin
In-Reply-To: <1767929389-143957-1-git-send-email-shawn.lin@rock-chips.com>
Rockchip platforms provide a 64x4 bytes debug FIFO to trace the
LTSSM history. Any LTSSM change will be recorded. It's userful
for debug purpose, for example link failure, etc.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---
Changes in v2:
- use tracepoint
drivers/pci/controller/dwc/pcie-dw-rockchip.c | 92 +++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
index 352f513..be9639aa 100644
--- a/drivers/pci/controller/dwc/pcie-dw-rockchip.c
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -22,6 +22,8 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
+#include <linux/workqueue.h>
+#include <trace/events/pci_controller.h>
#include "../../pci.h"
#include "pcie-designware.h"
@@ -73,6 +75,18 @@
#define PCIE_CLIENT_CDM_RASDES_TBA_L1_1 BIT(4)
#define PCIE_CLIENT_CDM_RASDES_TBA_L1_2 BIT(5)
+/* Debug FIFO information */
+#define PCIE_CLIENT_DBG_FIFO_MODE_CON 0x310
+#define PCIE_CLIENT_DBG_EN 0xffff0007
+#define PCIE_CLIENT_DBG_DIS 0xffff0000
+#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
+#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
+#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
+#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
+#define PCIE_CLIENT_DBG_TRANSITION_DATA 0xffff0000
+#define PCIE_CLIENT_DBG_FIFO_STATUS 0x350
+#define PCIE_DBG_LTSSM_HISTORY_CNT 64
+
/* Hot Reset Control Register */
#define PCIE_CLIENT_HOT_RESET_CTRL 0x180
#define PCIE_LTSSM_APP_DLY2_EN BIT(1)
@@ -96,6 +110,7 @@ struct rockchip_pcie {
struct irq_domain *irq_domain;
const struct rockchip_pcie_of_data *data;
bool supports_clkreq;
+ struct delayed_work trace_work;
};
struct rockchip_pcie_of_data {
@@ -206,6 +221,79 @@ static enum dw_pcie_ltssm rockchip_pcie_get_ltssm(struct dw_pcie *pci)
return rockchip_pcie_get_ltssm_reg(rockchip) & PCIE_LTSSM_STATUS_MASK;
}
+#ifdef CONFIG_TRACING
+static void rockchip_pcie_ltssm_trace_work(struct work_struct *work)
+{
+ struct rockchip_pcie *rockchip = container_of(work, struct rockchip_pcie,
+ trace_work.work);
+ struct dw_pcie *pci = &rockchip->pci;
+ enum dw_pcie_ltssm state;
+ u32 val, rate, l1ss, loop, prev_val = DW_PCIE_LTSSM_UNKNOWN;
+
+ for (loop = 0; loop < PCIE_DBG_LTSSM_HISTORY_CNT; loop++) {
+ val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_DBG_FIFO_STATUS);
+ rate = (val & GENMASK(22, 20)) >> 20;
+ l1ss = (val & GENMASK(10, 8)) >> 8;
+ val &= PCIE_LTSSM_STATUS_MASK;
+
+ /* Two consecutive identical LTSSM means invalid subsequent data */
+ if ((loop > 0 && val == prev_val) || val > DW_PCIE_LTSSM_RCVRY_EQ3)
+ break;
+
+ state = prev_val = val;
+ if (val == DW_PCIE_LTSSM_L1_IDLE) {
+ if (l1ss == 2)
+ state = DW_PCIE_LTSSM_L1_2;
+ else if (l1ss == 1)
+ state = DW_PCIE_LTSSM_L1_1;
+ }
+
+ trace_pcie_ltssm_state_transition(dev_name(pci->dev),
+ dw_pcie_ltssm_status_string(state),
+ ((rate + 1) > pci->max_link_speed) ?
+ PCI_SPEED_UNKNOWN : PCIE_SPEED_2_5GT + rate);
+ }
+
+ schedule_delayed_work(&rockchip->trace_work, msecs_to_jiffies(5000));
+}
+
+static void rockchip_pcie_ltssm_trace(struct rockchip_pcie *rockchip,
+ bool en)
+{
+ if (en) {
+ rockchip_pcie_writel_apb(rockchip,
+ PCIE_CLIENT_DBG_TRANSITION_DATA,
+ PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0);
+ rockchip_pcie_writel_apb(rockchip,
+ PCIE_CLIENT_DBG_TRANSITION_DATA,
+ PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1);
+ rockchip_pcie_writel_apb(rockchip,
+ PCIE_CLIENT_DBG_TRANSITION_DATA,
+ PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0);
+ rockchip_pcie_writel_apb(rockchip,
+ PCIE_CLIENT_DBG_TRANSITION_DATA,
+ PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1);
+ rockchip_pcie_writel_apb(rockchip,
+ PCIE_CLIENT_DBG_EN,
+ PCIE_CLIENT_DBG_FIFO_MODE_CON);
+
+ INIT_DELAYED_WORK(&rockchip->trace_work,
+ rockchip_pcie_ltssm_trace_work);
+ schedule_delayed_work(&rockchip->trace_work, 0);
+ } else {
+ rockchip_pcie_writel_apb(rockchip,
+ PCIE_CLIENT_DBG_DIS,
+ PCIE_CLIENT_DBG_FIFO_MODE_CON);
+ cancel_delayed_work_sync(&rockchip->trace_work);
+ }
+}
+#else
+static void rockchip_pcie_ltssm_trace(struct rockchip_pcie *rockchip,
+ bool en)
+{
+}
+#endif
+
static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip)
{
rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM,
@@ -289,6 +377,9 @@ static int rockchip_pcie_start_link(struct dw_pcie *pci)
* 100us as we don't know how long should the device need to reset.
*/
msleep(PCIE_T_PVPERL_MS);
+
+ rockchip_pcie_ltssm_trace(rockchip, true);
+
gpiod_set_value_cansleep(rockchip->rst_gpio, 1);
return 0;
@@ -299,6 +390,7 @@ static void rockchip_pcie_stop_link(struct dw_pcie *pci)
struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
rockchip_pcie_disable_ltssm(rockchip);
+ rockchip_pcie_ltssm_trace(rockchip, false);
}
static int rockchip_pcie_host_init(struct dw_pcie_rp *pp)
--
2.7.4
^ permalink raw reply related
* [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
From: Jiri Olsa @ 2026-01-09 9:34 UTC (permalink / raw)
To: Masami Hiramatsu, Steven Rostedt, Will Deacon
Cc: Mahe Tardy, Peter Zijlstra, bpf, linux-trace-kernel,
linux-arm-kernel, x86, Yonghong Song, Song Liu, Andrii Nakryiko,
Mark Rutland
Mahe reported issue with bpf_override_return helper not working when
executed from kprobe.multi bpf program on arm.
The problem is that on arm we use alternate storage for pt_regs object
that is passed to bpf_prog_run and if any register is changed (which
is the case of bpf_override_return) it's not propagated back to actual
pt_regs object.
Fixing this by introducing and calling ftrace_partial_regs_update function
to propagate the values of changed registers (ip and stack).
Reported-by: Mahe Tardy <mahe.tardy@gmail.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
v2 changes:
- moved ftrace_partial_regs_update to generic code [Will]
include/linux/ftrace_regs.h | 25 +++++++++++++++++++++++++
kernel/trace/bpf_trace.c | 1 +
2 files changed, 26 insertions(+)
diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
index 15627ceea9bc..f9a7c009cdae 100644
--- a/include/linux/ftrace_regs.h
+++ b/include/linux/ftrace_regs.h
@@ -33,6 +33,31 @@ struct ftrace_regs;
#define ftrace_regs_get_frame_pointer(fregs) \
frame_pointer(&arch_ftrace_regs(fregs)->regs)
+static __always_inline void
+ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs) { }
+
+#else
+
+/*
+ * ftrace_partial_regs_update - update the original ftrace_regs from regs
+ * @fregs: The ftrace_regs to update from @regs
+ * @regs: The partial regs from ftrace_partial_regs() that was updated
+ *
+ * Some architectures have the partial regs living in the ftrace_regs
+ * structure, whereas other architectures need to make a different copy
+ * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and
+ * if the code using @regs updates a field (like the instruction pointer or
+ * stack pointer) it may need to propagate that change to the original @fregs
+ * it retrieved the partial @regs from. Use this function to guarantee that
+ * update happens.
+ */
+static __always_inline void
+ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
+{
+ ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
+ ftrace_regs_set_return_value(fregs, regs_return_value(regs));
+}
+
#endif /* HAVE_ARCH_FTRACE_REGS */
/* This can be overridden by the architectures */
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 6e076485bf70..3a17f79b20c2 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2564,6 +2564,7 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link,
old_run_ctx = bpf_set_run_ctx(&run_ctx.session_ctx.run_ctx);
err = bpf_prog_run(link->link.prog, regs);
bpf_reset_run_ctx(old_run_ctx);
+ ftrace_partial_regs_update(fregs, bpf_kprobe_multi_pt_regs_ptr());
rcu_read_unlock();
out:
--
2.52.0
^ permalink raw reply related
* [PATCHv2 bpf-next 2/2] selftests/bpf: Add test for bpf_override_return helper
From: Jiri Olsa @ 2026-01-09 9:34 UTC (permalink / raw)
To: Masami Hiramatsu, Steven Rostedt, Will Deacon
Cc: Song Liu, Peter Zijlstra, bpf, linux-trace-kernel,
linux-arm-kernel, x86, Yonghong Song, Song Liu, Andrii Nakryiko,
Mark Rutland, Mahe Tardy
In-Reply-To: <20260109093454.389295-1-jolsa@kernel.org>
We do not actually test the bpf_override_return helper functionality
itself at the moment, only the bpf program being able to attach it.
Adding test that override prctl syscall return value on top of
kprobe and kprobe.multi.
Acked-by: Song Liu <song@kernel.org>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
.../bpf/prog_tests/kprobe_multi_test.c | 44 +++++++++++++++++++
.../bpf/progs/kprobe_multi_override.c | 15 +++++++
tools/testing/selftests/bpf/trace_helpers.h | 12 +++++
3 files changed, 71 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
index 6cfaa978bc9a..9caef222e528 100644
--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
@@ -1,4 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
+#include <errno.h>
+#include <sys/prctl.h>
#include <test_progs.h>
#include "kprobe_multi.skel.h"
#include "trace_helpers.h"
@@ -540,6 +542,46 @@ static void test_attach_override(void)
kprobe_multi_override__destroy(skel);
}
+static void test_override(void)
+{
+ struct kprobe_multi_override *skel = NULL;
+ int err;
+
+ skel = kprobe_multi_override__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load"))
+ goto cleanup;
+
+ skel->bss->pid = getpid();
+
+ /* no override */
+ err = prctl(0xffff, 0);
+ ASSERT_EQ(err, -1, "err");
+
+ /* kprobe.multi override */
+ skel->links.test_override = bpf_program__attach_kprobe_multi_opts(skel->progs.test_override,
+ SYS_PREFIX "sys_prctl", NULL);
+ if (!ASSERT_OK_PTR(skel->links.test_override, "bpf_program__attach_kprobe_multi_opts"))
+ goto cleanup;
+
+ err = prctl(0xffff, 0);
+ ASSERT_EQ(err, 123, "err");
+
+ bpf_link__destroy(skel->links.test_override);
+ skel->links.test_override = NULL;
+
+ /* kprobe override */
+ skel->links.test_kprobe_override = bpf_program__attach_kprobe(skel->progs.test_kprobe_override,
+ false, SYS_PREFIX "sys_prctl");
+ if (!ASSERT_OK_PTR(skel->links.test_kprobe_override, "bpf_program__attach_kprobe"))
+ goto cleanup;
+
+ err = prctl(0xffff, 0);
+ ASSERT_EQ(err, 123, "err");
+
+cleanup:
+ kprobe_multi_override__destroy(skel);
+}
+
#ifdef __x86_64__
static void test_attach_write_ctx(void)
{
@@ -597,6 +639,8 @@ void test_kprobe_multi_test(void)
test_attach_api_fails();
if (test__start_subtest("attach_override"))
test_attach_override();
+ if (test__start_subtest("override"))
+ test_override();
if (test__start_subtest("session"))
test_session_skel_api();
if (test__start_subtest("session_cookie"))
diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi_override.c b/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
index 28f8487c9059..14f39fa6d515 100644
--- a/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
+++ b/tools/testing/selftests/bpf/progs/kprobe_multi_override.c
@@ -5,9 +5,24 @@
char _license[] SEC("license") = "GPL";
+int pid = 0;
+
SEC("kprobe.multi")
int test_override(struct pt_regs *ctx)
{
+ if (bpf_get_current_pid_tgid() >> 32 != pid)
+ return 0;
+
+ bpf_override_return(ctx, 123);
+ return 0;
+}
+
+SEC("kprobe")
+int test_kprobe_override(struct pt_regs *ctx)
+{
+ if (bpf_get_current_pid_tgid() >> 32 != pid)
+ return 0;
+
bpf_override_return(ctx, 123);
return 0;
}
diff --git a/tools/testing/selftests/bpf/trace_helpers.h b/tools/testing/selftests/bpf/trace_helpers.h
index 9437bdd4afa5..a5576b2dfc26 100644
--- a/tools/testing/selftests/bpf/trace_helpers.h
+++ b/tools/testing/selftests/bpf/trace_helpers.h
@@ -4,6 +4,18 @@
#include <bpf/libbpf.h>
+#ifdef __x86_64__
+#define SYS_PREFIX "__x64_"
+#elif defined(__s390x__)
+#define SYS_PREFIX "__s390x_"
+#elif defined(__aarch64__)
+#define SYS_PREFIX "__arm64_"
+#elif defined(__riscv)
+#define SYS_PREFIX "__riscv_"
+#else
+#define SYS_PREFIX ""
+#endif
+
#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
--
2.52.0
^ permalink raw reply related
* Re: [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
From: bot+bpf-ci @ 2026-01-09 10:00 UTC (permalink / raw)
To: jolsa, mhiramat, rostedt, will
Cc: mahe.tardy, peterz, bpf, linux-trace-kernel, linux-arm-kernel,
x86, yhs, songliubraving, andrii, mark.rutland, ast, andrii,
daniel, martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
In-Reply-To: <20260109093454.389295-1-jolsa@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 1539 bytes --]
> diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
> index 15627ceea9bc..f9a7c009cdae 100644
> --- a/include/linux/ftrace_regs.h
> +++ b/include/linux/ftrace_regs.h
> @@ -33,6 +33,31 @@ struct ftrace_regs;
[ ... ]
> +#else
> +
> +/*
> + * ftrace_partial_regs_update - update the original ftrace_regs from regs
> + * @fregs: The ftrace_regs to update from @regs
> + * @regs: The partial regs from ftrace_partial_regs() that was updated
[ ... ]
> + */
> +static __always_inline void
> +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> + ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
> + ftrace_regs_set_return_value(fregs, regs_return_value(regs));
^^^^^
Should the fregs parameter be non-const here? On architectures with
HAVE_ARCH_FTRACE_REGS (arm64, riscv), the setter functions expect a
non-const pointer:
ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, ...)
ftrace_regs_set_return_value(struct ftrace_regs *fregs, ...)
Passing the const-qualified fregs to these functions discards the const
qualifier, which may cause compiler warnings with -Werror or undefined
behavior since the setters do modify the ftrace_regs structure.
> +}
> +
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/20847954035
^ permalink raw reply
* [PATCH v13] dma-buf: add some tracepoints to debug.
From: Xiang Gao @ 2026-01-09 11:54 UTC (permalink / raw)
To: sumit.semwal, christian.koenig, rostedt, mhiramat
Cc: linux-media, dri-devel, linux-kernel, mathieu.desnoyers, dhowells,
kuba, brauner, akpm, linux-trace-kernel, gaoxiang17
In-Reply-To: <7e126504-1966-4c63-8db5-dfe57e206169@amd.com/>
From: gaoxiang17 <gaoxiang17@xiaomi.com>
Since we can only inspect dmabuf by iterating over process FDs or the
dmabuf_list, we need to add our own tracepoints to track its status in
real time in production.
For example:
binder:3016_1-3102 [006] ...1. 255.126521: dma_buf_export: exp_name=qcom,system size=12685312 ino=2738
binder:3016_1-3102 [006] ...1. 255.126528: dma_buf_fd: exp_name=qcom,system size=12685312 ino=2738 fd=8
binder:3016_1-3102 [006] ...1. 255.126642: dma_buf_mmap_internal: exp_name=qcom,system size=28672 ino=2739
kworker/6:1-86 [006] ...1. 255.127194: dma_buf_put: exp_name=qcom,system size=12685312 ino=2738
RenderThread-9293 [006] ...1. 316.618179: dma_buf_get: exp_name=qcom,system size=12771328 ino=2762 fd=176
RenderThread-9293 [006] ...1. 316.618195: dma_buf_dynamic_attach: exp_name=qcom,system size=12771328 ino=2762 attachment:ffffff880a18dd00 is_dynamic=0 dev_name=kgsl-3d0
RenderThread-9293 [006] ...1. 318.878220: dma_buf_detach: exp_name=qcom,system size=12771328 ino=2762 attachment:ffffff880a18dd00 is_dynamic=0 dev_name=kgsl-3d0
Signed-off-by: Xiang Gao <gaoxiang17@xiaomi.com>
---
Changes since v12: https://lore.kernel.org/all/20251229031547.59272-1-gxxa03070307@gmail.com/
- list history changes
Changes since v11: https://lore.kernel.org/all/20251225121119.2194228-1-gxxa03070307@gmail.com/
- Lined up the backslashes nicely for the macro DMA_BUF_TRACE.
- Used DEFINE_EVENT_CONDITION() to move the condition branch into the tracepoint.
Changes since v10: https://lore.kernel.org/all/20251224013455.1649879-1-gxxa03070307@gmail.com/
- Always expose dmabuf->name_lock if lockdep is enabled.
Changes since v9: https://lore.kernel.org/all/20251223032749.1371913-1-gxxa03070307@gmail.com/
- Fixed some whitespace issues with the macro DMA_BUF_TRACE again.
Changes since v8: https://lore.kernel.org/all/20251218062853.819744-1-gxxa03070307@gmail.com/
- Expose dmabuf->name_lock when lockdep is enabled but trace event is not.
Changes since v7: https://lore.kernel.org/all/20251217105132.643300-1-gxxa03070307@gmail.com/
- Fixed some whitespace issues with the macro DMA_BUF_TRACE.
Changes since v6: https://lore.kernel.org/all/20251216063952.516364-1-gxxa03070307@gmail.com/
- Add a comment for the macro DMA_BUF_TRACE.
Changes since v5: https://lore.kernel.org/all/20251201112148.843572-1-gxxa03070307@gmail.com/
- Add the macro DMA_BUF_TRACE.
- Modify the commit message.
Changes since v4: https://lore.kernel.org/all/20251128085215.550100-1-gxxa03070307@gmail.com/
- Remove the tracepoints exporting.
- Remove the file refcount for the trace.
- Print the dev_name last.
- Add the parameter of whether dma_buf attachment is dynamic.
Changes since v3: https://lore.kernel.org/all/20251127004352.376307-1-gxxa03070307@gmail.com/
- Take the dmabuf->name_lock around the tracepoint call itself.
- Used DECLARE_EVENT_CLASS() and a DEFINE_EVENT().
Changes since v2: https://lore.kernel.org/all/20251125162949.220488-1-gxxa03070307@gmail.com/
- Add more explanation to the commit message.
drivers/dma-buf/dma-buf.c | 9 ++----
include/trace/events/dma_buf.h | 50 ++++++++++++++++++----------------
2 files changed, 29 insertions(+), 30 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index a4d8f2ff94e4..ac4238063ec1 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -48,12 +48,10 @@
*/
#define DMA_BUF_TRACE(FUNC, ...) \
do { \
- if (FUNC##_enabled()) { \
+ /* Always expose lock if lockdep is enabled */ \
+ if (IS_ENABLED(CONFIG_LOCKDEP) || FUNC##_enabled()) { \
guard(spinlock)(&dmabuf->name_lock); \
FUNC(__VA_ARGS__); \
- } else if (IS_ENABLED(CONFIG_LOCKDEP)) { \
- /* Expose this lock when lockdep is enabled */ \
- guard(spinlock)(&dmabuf->name_lock); \
} \
} while (0)
@@ -806,8 +804,7 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags)
return -EINVAL;
fd = FD_ADD(flags, dmabuf->file);
- if (fd >= 0)
- DMA_BUF_TRACE(trace_dma_buf_fd, dmabuf, fd);
+ DMA_BUF_TRACE(trace_dma_buf_fd, dmabuf, fd);
return fd;
}
diff --git a/include/trace/events/dma_buf.h b/include/trace/events/dma_buf.h
index 35f8140095f4..3bb88d05bcc8 100644
--- a/include/trace/events/dma_buf.h
+++ b/include/trace/events/dma_buf.h
@@ -15,15 +15,15 @@ DECLARE_EVENT_CLASS(dma_buf,
TP_ARGS(dmabuf),
TP_STRUCT__entry(
- __string(exp_name, dmabuf->exp_name)
- __field(size_t, size)
- __field(ino_t, ino)
+ __string( exp_name, dmabuf->exp_name)
+ __field( size_t, size)
+ __field( ino_t, ino)
),
TP_fast_assign(
__assign_str(exp_name);
- __entry->size = dmabuf->size;
- __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
),
TP_printk("exp_name=%s size=%zu ino=%lu",
@@ -40,21 +40,21 @@ DECLARE_EVENT_CLASS(dma_buf_attach_dev,
TP_ARGS(dmabuf, attach, is_dynamic, dev),
TP_STRUCT__entry(
- __string(dev_name, dev_name(dev))
- __string(exp_name, dmabuf->exp_name)
- __field(size_t, size)
- __field(ino_t, ino)
- __field(struct dma_buf_attachment *, attach)
- __field(bool, is_dynamic)
+ __string( dev_name, dev_name(dev))
+ __string( exp_name, dmabuf->exp_name)
+ __field( size_t, size)
+ __field( ino_t, ino)
+ __field( struct dma_buf_attachment *, attach)
+ __field( bool, is_dynamic)
),
TP_fast_assign(
__assign_str(dev_name);
__assign_str(exp_name);
- __entry->size = dmabuf->size;
- __entry->ino = dmabuf->file->f_inode->i_ino;
- __entry->is_dynamic = is_dynamic;
- __entry->attach = attach;
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->is_dynamic = is_dynamic;
+ __entry->attach = attach;
),
TP_printk("exp_name=%s size=%zu ino=%lu attachment:%p is_dynamic=%d dev_name=%s",
@@ -73,17 +73,17 @@ DECLARE_EVENT_CLASS(dma_buf_fd,
TP_ARGS(dmabuf, fd),
TP_STRUCT__entry(
- __string(exp_name, dmabuf->exp_name)
- __field(size_t, size)
- __field(ino_t, ino)
- __field(int, fd)
+ __string( exp_name, dmabuf->exp_name)
+ __field( size_t, size)
+ __field( ino_t, ino)
+ __field( int, fd)
),
TP_fast_assign(
__assign_str(exp_name);
- __entry->size = dmabuf->size;
- __entry->ino = dmabuf->file->f_inode->i_ino;
- __entry->fd = fd;
+ __entry->size = dmabuf->size;
+ __entry->ino = dmabuf->file->f_inode->i_ino;
+ __entry->fd = fd;
),
TP_printk("exp_name=%s size=%zu ino=%lu fd=%d",
@@ -137,11 +137,13 @@ DEFINE_EVENT(dma_buf_attach_dev, dma_buf_detach,
TP_ARGS(dmabuf, attach, is_dynamic, dev)
);
-DEFINE_EVENT(dma_buf_fd, dma_buf_fd,
+DEFINE_EVENT_CONDITION(dma_buf_fd, dma_buf_fd,
TP_PROTO(struct dma_buf *dmabuf, int fd),
- TP_ARGS(dmabuf, fd)
+ TP_ARGS(dmabuf, fd),
+
+ TP_CONDITION(fd >= 0)
);
DEFINE_EVENT(dma_buf_fd, dma_buf_get,
--
2.34.1
^ permalink raw reply related
* Re: [PATCHv2 bpf-next 1/2] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run
From: Will Deacon @ 2026-01-09 13:47 UTC (permalink / raw)
To: Jiri Olsa
Cc: Masami Hiramatsu, Steven Rostedt, Mahe Tardy, Peter Zijlstra, bpf,
linux-trace-kernel, linux-arm-kernel, x86, Yonghong Song,
Song Liu, Andrii Nakryiko, Mark Rutland
In-Reply-To: <20260109093454.389295-1-jolsa@kernel.org>
On Fri, Jan 09, 2026 at 10:34:53AM +0100, Jiri Olsa wrote:
> Mahe reported issue with bpf_override_return helper not working when
> executed from kprobe.multi bpf program on arm.
>
> The problem is that on arm we use alternate storage for pt_regs object
> that is passed to bpf_prog_run and if any register is changed (which
> is the case of bpf_override_return) it's not propagated back to actual
> pt_regs object.
>
> Fixing this by introducing and calling ftrace_partial_regs_update function
> to propagate the values of changed registers (ip and stack).
>
> Reported-by: Mahe Tardy <mahe.tardy@gmail.com>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
> v2 changes:
> - moved ftrace_partial_regs_update to generic code [Will]
>
> include/linux/ftrace_regs.h | 25 +++++++++++++++++++++++++
> kernel/trace/bpf_trace.c | 1 +
> 2 files changed, 26 insertions(+)
>
> diff --git a/include/linux/ftrace_regs.h b/include/linux/ftrace_regs.h
> index 15627ceea9bc..f9a7c009cdae 100644
> --- a/include/linux/ftrace_regs.h
> +++ b/include/linux/ftrace_regs.h
> @@ -33,6 +33,31 @@ struct ftrace_regs;
> #define ftrace_regs_get_frame_pointer(fregs) \
> frame_pointer(&arch_ftrace_regs(fregs)->regs)
>
> +static __always_inline void
> +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs) { }
> +
> +#else
> +
> +/*
> + * ftrace_partial_regs_update - update the original ftrace_regs from regs
> + * @fregs: The ftrace_regs to update from @regs
> + * @regs: The partial regs from ftrace_partial_regs() that was updated
> + *
> + * Some architectures have the partial regs living in the ftrace_regs
> + * structure, whereas other architectures need to make a different copy
> + * of the @regs. If a partial @regs is retrieved by ftrace_partial_regs() and
> + * if the code using @regs updates a field (like the instruction pointer or
> + * stack pointer) it may need to propagate that change to the original @fregs
> + * it retrieved the partial @regs from. Use this function to guarantee that
> + * update happens.
> + */
> +static __always_inline void
> +ftrace_partial_regs_update(const struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> + ftrace_regs_set_instruction_pointer(fregs, instruction_pointer(regs));
> + ftrace_regs_set_return_value(fregs, regs_return_value(regs));
> +}
I think the AI thingy is right about dropping the const qualifier here
but overall I prefer this to the previous revisions. Thanks for sticking
with it!
Acked-by: Will Deacon <will@kernel.org>
Will
^ permalink raw reply
* Re: [PATCH] powerpc64/bpf: support direct_call on livepatch function
From: Naveen N Rao @ 2026-01-09 13:48 UTC (permalink / raw)
To: Hari Bathini
Cc: Madhavan Srinivasan, linuxppc-dev, Christophe Leroy,
Michael Ellerman, Nicholas Piggin, bpf, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko, Song Liu, Jiri Olsa,
Viktor Malik, live-patching, Josh Poimboeuf, Joe Lawrence,
Jiri Kosina, linux-trace-kernel, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Shung-Hsi Yu
In-Reply-To: <e34ddd05-d926-4eb4-b861-4bf8fd5635bb@linux.ibm.com>
On Mon, Dec 08, 2025 at 10:05:44PM +0530, Hari Bathini wrote:
> >
> > One of the other thoughts I had was if we could stuff the function
> > address into the ftrace OOL stub. I had considered this back when I
> > implemented the OOL stubs, but didn't do it due to the extra memory
> > requirement. However, given the dance we're having to do, I'm now
> > thinking that may make sense and can simplify the code. If we can also
> > hook into livepatch, then we should be able to update the function
> > address in the stub to point to the new address and the trampoline
> > should then "just work" since it already saves/restores the TOC [We may
> > additionally have to update the function IP in _R12, but that would be a
> > minor change overall]
> >
> > We will still need a way to restore livepatch TOC if the BPF trampoline
> > doesn't itself call into the function, but we may be able to handle that
> > if we change the return address to jump to a stub that restores the TOC
> > from the livepatch stack.
>
> Sounds doable. Looking into a couple of other things at the moment
> though. Will try out this suggestion and get back post that.
> Having said that, your thoughts on whether the current approach
> is a viable option if bpf_get_func_ip() can be fixed somehow?
Oh, that's fine -- feel free to go with whatever approach you think
works best.
- Naveen
^ permalink raw reply
* Re: [PATCH 1/3] powerpc64: make clang cross-build friendly
From: Naveen N Rao @ 2026-01-09 13:50 UTC (permalink / raw)
To: Hari Bathini
Cc: linuxppc-dev, Madhavan Srinivasan, Christophe Leroy,
Michael Ellerman, linux-trace-kernel, Mark Rutland,
Steven Rostedt, Masami Hiramatsu, llvm, Maryam Moghadas
In-Reply-To: <8141c6eb-f2b7-4a19-b637-af699bb8d5c4@linux.ibm.com>
On Mon, Dec 08, 2025 at 09:32:06PM +0530, Hari Bathini wrote:
> Thanks for the review, Naveen.
>
> On 24/11/25 11:19 am, Naveen N Rao wrote:
> > On Sun, Nov 09, 2025 at 02:34:03AM +0530, Hari Bathini wrote:
> > > ARCH_USING_PATCHABLE_FUNCTION_ENTRY depends on toolchain support for
> > > -fpatchable-function-entry option. The current script that checks
> > > for this support only handles GCC. Rename the script and extend it
> > > to detect support for -fpatchable-function-entry with Clang as well,
> > > allowing clean cross-compilation with Clang toolchains.
> > >
> > > Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
> > > ---
> > > arch/powerpc/Kconfig | 5 +++--
> > > ...-function-entry.sh => check-fpatchable-function-entry.sh} | 0
> > > 2 files changed, 3 insertions(+), 2 deletions(-)
> > > rename arch/powerpc/tools/{gcc-check-fpatchable-function-entry.sh => check-fpatchable-function-entry.sh} (100%)
> > >
> > > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > > index 325c1171894d..dfb62e211c92 100644
> > > --- a/arch/powerpc/Kconfig
> > > +++ b/arch/powerpc/Kconfig
> > > @@ -568,8 +568,9 @@ config ARCH_USING_PATCHABLE_FUNCTION_ENTRY
> > > depends on FUNCTION_TRACER && (PPC32 || PPC64_ELF_ABI_V2)
> > > depends on $(cc-option,-fpatchable-function-entry=2)
> > > def_bool y if PPC32
> > > - def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mlittle-endian) if PPC64 && CPU_LITTLE_ENDIAN
> > > - def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mbig-endian) if PPC64 && CPU_BIG_ENDIAN
> > > + def_bool $(success,$(srctree)/arch/powerpc/tools/check-fpatchable-function-entry.sh $(CC) -mlittle-endian) if PPC64 && CPU_LITTLE_ENDIAN && CC_IS_GCC
> > > + def_bool $(success,$(srctree)/arch/powerpc/tools/check-fpatchable-function-entry.sh $(CC) -target ppc64le -mlittle-endian) if PPC64 && CPU_LITTLE_ENDIAN && CC_IS_CLANG
> >
> > Can you instead pass $(CLANG_FLAGS) to retain the same command across
> > gcc/clang?
>
> Should work, I guess.
> But do I need to test for any additional clang flags that
> may interfere with what we are trying to check here?
From what I can tell, $(CLANG_FLAGS) includes a fairly static set of
flags which will be included alongside other $CFLAGS. So, I don't think
anything special should be needed there.
- Naveen
^ permalink raw reply
* Re: [PATCH v13 mm-new 00/16] khugepaged: mTHP support
From: David Hildenbrand (Red Hat) @ 2026-01-09 13:57 UTC (permalink / raw)
To: Lorenzo Stoakes, Nico Pache
Cc: linux-kernel, linux-trace-kernel, linux-mm, linux-doc, ziy,
baolin.wang, Liam.Howlett, ryan.roberts, dev.jain, corbet,
rostedt, mhiramat, mathieu.desnoyers, akpm, baohua, willy, peterx,
wangkefeng.wang, usamaarif642, sunnanyong, vishal.moola,
thomas.hellstrom, yang, kas, aarcange, raquini, anshuman.khandual,
catalin.marinas, tiwai, will, dave.hansen, jack, cl, jglisse,
surenb, zokeefe, hannes, rientjes, mhocko, rdunlap, hughd,
richard.weiyang, lance.yang, vbabka, rppt, jannh, pfalcato
In-Reply-To: <e54b6ade-e2a0-4a68-93c4-23af85479567@lucifer.local>
On 1/8/26 18:19, Lorenzo Stoakes wrote:
> (Sorry for multiple mails replying to same, lei/lore are broken again so my
> setup isn't working properly).
>
> I tried to fixup the conflicts here to run tests locally but there's too many
> and I messed it up.
>
> Could you please resend this series rebased on mm-unstable please?
And maybe send out the two cleanups that can be applied earlier separately?
--
Cheers
David
^ permalink raw reply
* Re: [PATCH v13 mm-new 00/16] khugepaged: mTHP support
From: Lorenzo Stoakes @ 2026-01-09 13:59 UTC (permalink / raw)
To: David Hildenbrand (Red Hat)
Cc: Nico Pache, linux-kernel, linux-trace-kernel, linux-mm, linux-doc,
ziy, baolin.wang, Liam.Howlett, ryan.roberts, dev.jain, corbet,
rostedt, mhiramat, mathieu.desnoyers, akpm, baohua, willy, peterx,
wangkefeng.wang, usamaarif642, sunnanyong, vishal.moola,
thomas.hellstrom, yang, kas, aarcange, raquini, anshuman.khandual,
catalin.marinas, tiwai, will, dave.hansen, jack, cl, jglisse,
surenb, zokeefe, hannes, rientjes, mhocko, rdunlap, hughd,
richard.weiyang, lance.yang, vbabka, rppt, jannh, pfalcato
In-Reply-To: <4cfb49a2-f0fc-4796-83a6-91db3a0f2a97@kernel.org>
On Fri, Jan 09, 2026 at 02:57:16PM +0100, David Hildenbrand (Red Hat) wrote:
> On 1/8/26 18:19, Lorenzo Stoakes wrote:
> > (Sorry for multiple mails replying to same, lei/lore are broken again so my
> > setup isn't working properly).
> >
> > I tried to fixup the conflicts here to run tests locally but there's too many
> > and I messed it up.
> >
> > Could you please resend this series rebased on mm-unstable please?
>
>
> And maybe send out the two cleanups that can be applied earlier separately?
Yeah sounds sensible.
>
> --
> Cheers
>
> David
Cheers, Lorenzo
^ permalink raw reply
* Re: [PATCH V4 1/2] mm/khugepaged: map dirty/writeback pages failures to EAGAIN
From: David Hildenbrand (Red Hat) @ 2026-01-09 14:30 UTC (permalink / raw)
To: Shivank Garg, Andrew Morton, Lorenzo Stoakes
Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
Dev Jain, Barry Song, Lance Yang, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Zach O'Keefe, linux-mm,
linux-kernel, linux-trace-kernel, Branden Moore, wang lian
In-Reply-To: <20251215084615.5283-5-shivankg@amd.com>
On 12/15/25 09:46, Shivank Garg wrote:
> When collapse_file encounters dirty or writeback pages in file-backed
> mappings, it currently returns SCAN_FAIL which maps to -EINVAL. This is
> misleading as EINVAL suggests invalid arguments, whereas dirty/writeback
> pages represent transient conditions that may resolve on retry.
>
> Introduce SCAN_PAGE_DIRTY_OR_WRITEBACK to cover both dirty and writeback
> states, mapping it to -EAGAIN. For MADV_COLLAPSE, this provides userspace
> with a clear signal that retry may succeed after writeback completes.
> For khugepaged, this is harmless as it will naturally revisit the range
> during periodic scans after async writeback completes.
>
> Reported-by: Branden Moore <Branden.Moore@amd.com>
> Closes: https://lore.kernel.org/all/4e26fe5e-7374-467c-a333-9dd48f85d7cc@amd.com
> Fixes: 34488399fa08 ("mm/madvise: add file and shmem support to MADV_COLLAPSE")
> Reviewed-by: Dev Jain <dev.jain@arm.com>
> Reviewed-by: Lance Yang <lance.yang@linux.dev>
> Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
> Reviewed-by: wang lian <lianux.mm@gmail.com>
> Signed-off-by: Shivank Garg <shivankg@amd.com>
Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>
--
Cheers
David
^ permalink raw reply
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