San7o/linux-perf-event-example
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
linux-perf-event-example
========================
Example kernel module registering a software perf event throught a
Performance Monitor Unit (PMU);
Author: Giovanni Santini
Mail: giovanni.santini@proton.me
License: GPLv2
Overview
--------
Perf exists to provide an interface to generate and read counters to
the user for performance analysis. Usually, hardware vendors keep many
hardware counters that store various information about the hardware such
as number of cache misses or incorrect branch predictions, and they
are exposed to userspace through perf events. They use the perf_event
infrastructure, which is composed of per-cpu buffers and
events. Events can contain a counter (a number) and can be of several
types such as hardware or software. To register events, we use the
Performance Monitor Unit (PMU) which manages said events and provides
an interface to work with them.
The user interacts with the infrastructure through a single system
call, but this is usually done through the Perf CLI utility, which is
able to collect events and generate reports. The Perf command can also
access other types of events such as tracepoints from tracefs that use
the ftrace infrastructure, therefore it makes as a powerful debugging
tool.
This example module registers a performance monitor unit that keeps
a software counter that grows atomically each second. A `reader`
utility is also implemented to read this counter.
Compilation
-----------
To build and load the kernel module, you first need the kernel
sources. In addition to building the module, we will also build the
kernel and an image to boot it with qemu for development. This is
advised since kernel panics in your module may crash the system.
Download a kernel version:
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.19.3.tar.xz
tar -xvf linux-6.19.3.tar.xz && mv linux-6.19.3 linux
cd linux
make defconfig && make -j$(nproc)
cd ..
Build the module:
make KVERSION=6.19.3
Build the `reader` utility:
make reader
Clean the build:
make clean
Create an image, copy the module, and boot with qemu:
make img
make copy
make qemu
Usage
-----
Inside the image, you will find the module in the /root directory. You
can load it with `insmod`
insmod ./hello-perf.ko
Check messages in `dmeg`:
dmesg
Read counter:
perf stat -a -e hello_pmu// sleep 3
Or with the C example (check the hello message in dmesg to know
which number to use):
./reader 11
Remove the module with:
rmmod ./hello-perf.ko
Debugging
---------
Follow this guide to debug kernel modules with gdb:
https://www.kernel.org/doc/html/v6.17/process/debugging/gdb-kernel-debugging.html
cat /sys/module/<your_module_name>/sections/.text
make qemu-debug
gdb ./linux/arch/x86/boot/vmlinux
(gdb) target remote :1234
(gdb) add-symbol-file /path/to/your/module.ko 0xffffffffa0000000