How it works...

A tracepoint is inserted using the TRACE_EVENT macro. It inserts a callback in the kernel source that gets called with the tracepoint parameters as arguments. Tracepoints added with the TRACE_EVENT macro allow ftrace or any other tracer to use them. The callback inserts the trace at the calling tracer's ring buffer.

To insert a new tracepoint into the Linux kernel, define a new header file with a special format. By default, tracepoint kernel files are located in include/trace/events, but the kernel has functionality so that the header files can be located in a different path. This is useful when defining a tracepoint in a kernel module.

To use the tracepoint, the header file must be included in any file that inserts the tracepoint, and a single C file must define CREATE_TRACE_POINT. For example, to extend the hello world Linux kernel module we saw in a previous chapter with a tracepoint, add the following code to meta-bsp-custom/recipes-kernel/hello-world-tracepoint/files/hello_world.c:

#include <linux/module.h> 
#include "linux/timer.h" 
#define CREATE_TRACE_POINTS 
#include "trace.h" 
 
static struct timer_list hello_timer; 
 
void hello_timer_callback(unsigned long data) 
{ 
        char a[] = "Hello"; 
        char b[] = "World"; 
        printk("%s %s
",a,b); 
      /* Insert the static tracepoint */ 
        trace_log_dbg(a, b); 
      /* Trigger the timer again in 8 seconds */ 
        mod_timer(&hello_timer, jiffies + msecs_to_jiffies(8000)); 
} 
 
static int hello_world_init(void) 
{ 
      /* Setup a timer to fire in 2 seconds */ 
        setup_timer(&hello_timer, hello_timer_callback, 0); 
        mod_timer(&hello_timer, jiffies + msecs_to_jiffies(2000)); 
        return 0; 
} 
 
static void hello_world_exit(void) 
{ 
      /* Delete the timer */ 
        del_timer(&hello_timer); 
} 
 
module_init(hello_world_init); 
module_exit(hello_world_exit); 
 
MODULE_LICENSE("GPL v2"); 

The tracepoint header file in meta-bsp-custom/recipes-kernel/hello-world-tracepoint/files/trace.h would be as follows:

#undef TRACE_SYSTEM 
#define TRACE_SYSTEM log_dbg 
 
#if !defined(_HELLOWORLD_TRACE) || defined(TRACE_HEADER_MULTI_READ) 
#define _HELLOWORLD_TRACE 
 
#include <linux/tracepoint.h> 
 
TRACE_EVENT(log_dbg, 
            TP_PROTO(char *a, char *b), 
            TP_ARGS(a, b), 
            TP_STRUCT__entry( 
                    __string(a, a) 
                    __string(b, b)), 
            TP_fast_assign( 
                    __assign_str(a, a); 
                    __assign_str(b, b);), 
            TP_printk("log_dbg: a %s b %s", 
                      __get_str(a), __get_str(b)) 
        ); 
#endif 
 
/* This part must be outside protection */ 
#undef TRACE_INCLUDE_PATH 
#undef TRACE_INCLUDE_FILE 
#define TRACE_INCLUDE_PATH . 
#define TRACE_INCLUDE_FILE trace 
#include <trace/define_trace.h> 

And the module's Makefile file in meta-bsp-custom/recipes-kernel/hello-world-tracepoint/files/Makefile would look as follows:

obj-m   := hello_world.o 
CFLAGS_hello_world.o    += -I$(src) 
 
SRC := $(shell pwd) 
 
all: 
        $(MAKE) -C "$(KERNEL_SRC)" M="$(SRC)" 
 
modules_install: 
        $(MAKE) -C "$(KERNEL_SRC)" M="$(SRC)" modules_install 
 
clean: 
        rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c 
        rm -f Module.markers Module.symvers modules.order 
        rm -rf .tmp_versions Modules.symvers 

Note the highlighted line that includes the current folder in the search path for include files.

We can now build the module externally, as we saw in the Building external kernel modules recipe in Chapter 2, The BSP Layer:

$ cd /opt/yocto/fsl-community-bsp/sources/meta-bsp-custom/recipes- 
kernel/hello-world-tracepoint/files/
$ source /opt/poky/2.4/environment-setup-cortexa9hf-neon-poky-linux-
gnueabi
$ KERNEL_SRC=/opt/yocto/linux-wandboard make

If you have an existing Yocto build, you can also use it to build the kernel by doing the following:

$ KERNEL_SRC=/opt/yocto/fsl-community-bsp/wandboard/tmp/work-shared/wandboard/kernel-build-artifacts/ make  

The corresponding Yocto recipe is included in the source that accompanies the book.

After copying the resulting hello_world.ko module to the Wandboard's root filesystem, you can load it with the following:

# insmod hello_world.ko
Hello World  

You can now see a new log_dbg directory inside /sys/kernel/debug/tracing/events, which contains a log_dbg event tracepoint with the following format:

# cat /sys/kernel/debug/tracing/events/log_dbg/log_dbg/format
name: log_dbg
ID: 864
format:
        field:unsigned short common_type;       offset:0;       size:2; signed:0;
        field:unsigned char common_flags;       offset:2;       size:1; signed:0;
        field:unsigned char common_preempt_count;       offset:3;       size:1; signed:0;
        field:int common_pid;   offset:4;       size:4; signed:1;
    
        field:__data_loc char[] a;      offset:8;       size:4; signed:0;
        field:__data_loc char[] b;      offset:12;      size:4; signed:0;
    
print fmt: "log_dbg: a %s b %s", __get_str(a), __get_str(b) 

You can then enable the function tracer on the hello_timer_callback function:

# cd /sys/kernel/debug/tracing
# echo 1 > events/log_dbg/log_dbg/enable
# echo 1 > /sys/kernel/debug/tracing/tracing_on
# cat trace
<idle>-0     [000] .ns2    64.306483: log_dbg: log_dbg: a Hello b World  
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset