The Linux kernel provides an Arm PMU driver for counting events such as cycles, instructions, and cache metrics. This article explains how to use the Arm Linux PMU driver to gather performance information, using a device driver and a system call.
The steps covered are:
- Configure Linux kernel for profiling
- Confirm the device tree entry for the Arm PMU driver is included in the kernel
- Insert system calls into the Linux application to access performance information
- Begin by enabling profiling in the Linux kernel. While it isn't always easy to identify the minimal set of values to enable kernel features, for this example enable “Kernel performance events and counters” which is found under “General setup" and "Kernel Performance Events and Counters”.
- Enable “Profiling support” on the “General setup” menu.
- Once these options are enabled recompile the kernel as usual by following the instructions provided in the CPAK.
Device Tree Entry
- Below is the device tree entry for the PMU driver. All Arm Linux CPAKs for Arm Cortex-A53 and Cortex-A57 processors include this entry so no modification is needed. If you are working with your own Linux configuration confirm the PMU entry is present in the device tree.
- When the kernel boots the driver prints out a message:
hw perfevents: enabled with arm/armv8-pmuv3 PMU driver, 7 counters available
If this message is not in the kernel boot log check both the PMU driver device tree entry and the kernel configuration parameters listed above. If any of them are not correct the driver message will not appear.
Performance Information from a Linux Application
The perf_event_open system call can be used to obtain performance information from a Linux application. This system call does not have a glibc wrapper so it is called directly using syscall. Most of the available examples create a wrapper function, including the one shown in the manpage to make for easier usage.
- The process is similar to many other Linux system calls. First, get a file descriptor using open() and then use the file descriptor for other operations such as ioctl() and read().
- The perf_event_open system call uses a number of parameters to configure the events to be counted. Sticking with the simple case of instruction count, fill in the perf_event_attr data structure with the desired information, including information about:
- Start enabled or disabled
- Trace child processes or not
- Include hypervisor activity or not
- Include kernel activity or not
Other system call arguments include which event to trace (such as instructions), the process id to trace, and which CPUs to trace on.
A setup function to count instructions could look like this:
The Arm PMU driver and perf_event_open system call provide a far more robust solution for accessing the Arm PMU from Linux applications. The driver takes care of all of the accounting, event counter overflow handling, and provides many flexible options for tracing.
For situations where tracing many events is required, it may be overly cumbersome to use the perf_event_open system call. One of the features of perf_event_open is the ability to use a group file descriptor to create groups of events with one group leader and other group members with all events being traced as a group. While all of this is possible it may be helpful to look at the perf command, which comes with the Linux kernel and provides the ability to control the counters for entire applications.