Intel PCM in userspace Linux
Recently I have been using Intel® Performance Counter Monitor Tool quite heavily to obtain code performance. The tool has been designed to work with Nehalem, Westmere, Sandy Bridge and Ivy Bridge micro-architecture as well as with Atom (R), and I have to admit, it does its job flawlessly. However, one annoying drawback of using this tool in Linux is the fact that one must run the tool as root, to get performance results. I decided to fix this problem, and make it possible to obtain all the results in user space.
The problem
In order for Intel PCM to obtain results directly from the CPU, it must be able to issue ioctl
requests to the
processor. This is done through the Linux kernel, by reading / writing to:
The Linux kernel, comes with an MSR kernel module, responsible for quering the model-specific registers of the CPU which are control registers in the x86 instruction set used for debugging, program execution tracing, computer performance monitoring, and toggling certain CPU features. Ideally, executing:
should allow users which are not root to be able to read / write from the MSR devices, however, this is not the case, and executing the command above will result in reporting the same error from Intel PCM tool:
Try to execute modprobe msr
as root user and then
you also must have read and write permissions for /dev/cpu/*/msr
devices (/dev/msr*
for Android). The chown
command can help. Access to Intel(r) Performance Counter Monitor has denied (no MSR or PCI CFG space access).
I have inspected the code of the msr.c kernel module, and I figure it out that the problem is in
static int msr_open(struct inode *inode, struct file *file)
function:
The function capable makes sure that the user is root, and root only, and therefore, no matter what kind of permissions
are set to /dev/cpu/*/msr
, this function will return it the user is any other user than root.
The Solution
The simplest solution is to comment the function capable and avoid the check for root user. This solution is not safe. Having access to users other than root, can impose a serious vulnerability to the system. However, I am the only user having access to my machine, and I prefer productivity over safety.
In order to make the change, I need to recompile the kernel module, and replace the old msr.ko
module. Additionally
I can also benefit from udev
, to set the proper permissions to the kernel module, so I don’t have to redo them every
time the machine boots up. The good thing is that I can put everything into one simple Makefile:
The module can be built and installed using (must be logged in as root, not sudo):
And after executing modprobe msr
, everything else should magically work in user-space.