Re: [BUG] tracing: dynamic ftrace selftest detected failures
From: Mark Rutland <mark.rutland@arm.com>
Date: 2024-08-21 15:42:11
Also in:
lkml, llvm
On Wed, Aug 21, 2024 at 04:32:46PM +0100, Mark Rutland wrote:
On Wed, Aug 21, 2024 at 07:05:39AM +0900, Masami Hiramatsu wrote:quoted
On Tue, 20 Aug 2024 08:10:42 -0700 Sami Tolvanen [off-list ref] wrote:quoted
On Tue, Aug 20, 2024 at 3:48 AM Mark Rutland [off-list ref] wrote:quoted
On Tue, Aug 20, 2024 at 10:03:30AM +0900, Masami Hiramatsu wrote:quoted
On Mon, 19 Aug 2024 12:02:44 -0400 Steven Rostedt [off-list ref] wrote:quoted
On Tue, 20 Aug 2024 00:56:49 +0900 Masami Hiramatsu (Google) [off-list ref] wrote:quoted
quoted
We may need to add "noinline" or something to make sure those functions don't get inlined for LTO.Yeah, we need such option at least for function call test.Could you add the noinline, and if it fixes the issue send a patch?I found the target function already has "noinline". I tried to add noinline to the testing function (callsite), but it also did not work. I think "noinline" is for the compiler, but LTO is done by the linker.If LTO is breaking noinline, then that has much larger implications for noinstr code and similar, and means that LTO is unsound...The noinline attribute is preserved in LLVM IR, so it should continue to work with LTO. Which function are we talking about here? Are you sure the function was inlined instead of being dropped completely? Does marking the function __used help?We are talking about trace_selftest_startup_dynamic_tracing() in kernel/trace/trace_selftest.c. The callee is func() which is actually DYN_FTRACE_TEST_NAME() in kernel/trace/trace_selftest_dynamic.c. That function passed as pointer (but the compiler can embed it by constant propagation.)Ah, so IIUC the function isn't being inlined; the call is being optimized away becase callee() has no side-effects. That can happen without LTO if the caller is in the same compilation unit, and I have worked around that in the past by adding a barrier() into the callee.
FWIW, that was in samples/ftrace/ftrace-ops.c, where tracee_relevant() and
tracee_irrelevant() have the barrier():
| /*
| * Marked as noinline to ensure that an out-of-line traceable copy is
| * generated by the compiler.
| *
| * The barrier() ensures the compiler won't elide calls by determining there
| * are no side-effects.
| */
| static noinline void tracee_relevant(void)
| {
| barrier();
| }
... so we already have precedent for that in tracing code.
Mark.