Documentation/trace/ftrace-design.rst

Source file repositories/reference/linux-study-clean/Documentation/trace/ftrace-design.rst

File Facts

System
Linux kernel
Corpus path
Documentation/trace/ftrace-design.rst
Extension
.rst
Size
14467 bytes
Lines
396
Domain
Support Tooling And Documentation
Bucket
Documentation
Inferred role
Support Tooling And Documentation: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct dyn_arch_ftrace {
		/* No extra data needed */
	};

With the header out of the way, we can fill out the assembly code.  While we
did already create a mcount() function earlier, dynamic ftrace only wants a
stub function.  This is because the mcount() will only be used during boot
and then all references to it will be patched out never to return.  Instead,
the guts of the old mcount() will be used to create a new ftrace_caller()
function.  Because the two are hard to merge, it will most likely be a lot
easier to have two separate definitions split up by #ifdefs.  Same goes for
the ftrace_stub() as that will now be inlined in ftrace_caller().

Before we get confused anymore, let's check out some pseudo code so you can
implement your own stuff in assembly::

	void mcount(void)
	{
		return;
	}

	void ftrace_caller(void)
	{
		/* save all state needed by the ABI (see paragraph above) */

		unsigned long frompc = ...;
		unsigned long selfpc = <return address> - MCOUNT_INSN_SIZE;

	ftrace_call:
		ftrace_stub(frompc, selfpc);

		/* restore all state needed by the ABI */

	ftrace_stub:
		return;
	}

This might look a little odd at first, but keep in mind that we will be runtime
patching multiple things.  First, only functions that we actually want to trace
will be patched to call ftrace_caller().  Second, since we only have one tracer
active at a time, we will patch the ftrace_caller() function itself to call the
specific tracer in question.  That is the point of the ftrace_call label.

With that in mind, let's move on to the C code that will actually be doing the
runtime patching.  You'll need a little knowledge of your arch's opcodes in
order to make it through the next section.

Every arch has an init callback function.  If you need to do something early on
to initialize some state, this is the time to do that.  Otherwise, this simple
function below should be sufficient for most people::

	int __init ftrace_dyn_arch_init(void)
	{
		return 0;
	}

There are two functions that are used to do runtime patching of arbitrary
functions.  The first is used to turn the mcount call site into a nop (which
is what helps us retain runtime performance when not tracing).  The second is
used to turn the mcount call site into a call to an arbitrary location (but
typically that is ftracer_caller()).  See the general function definition in
linux/ftrace.h for the functions::

	ftrace_make_nop()
	ftrace_make_call()

The rec->ip value is the address of the mcount call site that was collected
by the scripts/recordmcount.pl during build time.

The last function is used to do runtime patching of the active tracer.  This

Annotation

Implementation Notes