An MSR-Based Performance monitoring tool for Intel Pentium processors running Linux (pdf)

Emanuele Altieri, Hampshire College (homepage)
Dominique Thiebaut, Smith College (homepage)

December 2001

Source Code and Binary Files

NOTE: The source code presented in this web page has been tested on a Linux RedHat 7.0, kernel 2.2.16-22. If you have any problem compiling on other distributions or kernels, feel free to email ealtieri@hampshire.edu.

The source code is available here and is organized into the following directories:

Each of these directories contains its own makefile. However, the msr directory contains itself a general makefile which will build everything.

The syntax of this makefile is the following:

$ make <module>

where module is the module that implements the MSR interface for a specific processor. A list of modules is available here

The make command will build the MSR Device Driver, the appropriate MSR Module and the monitor tools.

msr/dev

This directory contains the source code of our MSR Device Driver (msr.c and msr.h). To build the device driver type

$ make module

where module is the module that implements the MSR interface for a specific processor. A list of modules is available here

The makefile will build the kernel module msr.o. To load the device driver, log in as root and type the following command:

$ insmod msr.o

Then check the system log to see if the device driver has been registered:

$ tail /var/log/messages
....
....
....
Jun 14 14:42:14 ozventures kernel: msr: the module has been registered with major number 254

The major number assigned to the device is 254, in the example above. The OS dynamically assigns a major number to the device every time the driver is loaded, but if you wish you can select a specific major number by typing:

$ insmod msr.o msr_module_major=xxx

where xxx is a number between 1 and 254. Again, check /var/log/messages or /proc/devices to see if the module has been loaded. If the major number is already in use by some other kernel module, then the device driver cannot be loaded.

NOTE: the device driver checks the processor architecture to see if it matches the interface which the driver has been built for. If not, then the device driver cannot be loaded and an error message is sent to the system log.

Once the kernel module has been loaded, you need to create a node for it in the /dev directory:

$ mknod /dev/msr c 254 0

where "/dev/msr" is the name of the node to be created, "c" stands for character device, "254" is the device major number and "0" the minor number. You may also change the attributes of the node so that any user applicaton can access the MSR Device Driver:

$ chmod a+rw /dev/msr

To unload the kernel module, type:

$ rmmod msr

Once the kernel module has been loaded, the read() and write() file operations can be used to access the model specific registers. These file operations still take a file descriptor, a pointer and a counter as parameters, but the device driver reinterprets these parameters as following:

ssize_t read(int msr_fd, struct MSR* value, msr_t reg);
ssize_t write(int msr_fd, struct MSR* value, msr_t reg);

where msr_fd is the file descriptor for the device driver, value is an MSR structure containing the value of the model specific register, and reg is the MSR register to be read/written.

However, when accessing performance monitoring registers, it's reccomended to use the MSR modules, described in the following section.

msr/include

This directory contains the MSR modules. An MSR module implements performance-monitoring MSR operations on a particular processor. All of the modules provide the same, processor-indipendent interface (MSR Interface), while the processor-specific implementation of this interface is hidden in the module's body. Therefore, these modules can be exchanged without having to modify the code of the application that is using them.

The MSR Interface, defined in msrio.h, consists of the following operations:

The MSR Interface is automatically included in a program by including the file msr.h, which, in addition, links to the MSR Symbols of a specific processor.

Following is a list of the MSR modules that have been implemented so far:

MODULE PROCESSOR Implementation GCC Symbol
pentium.o Intel Pentium pentium.h, pentium.c __INTEL_P0__
pentium_mmx.o Intel Pentium MMX pentium_mmx.h, pentium_mmx.c __INTEL_PMMX__

To build an MSR module:

$ make module

msr/monitor

This directory contains tools for monitoring programs:

Files Index

msr/Makefile
msr/interfaces.txt
msr/dev/Makefile
msr/dev/msr.h
msr/dev/msr.c
msr/dev/msr.o
msr/include/Makefile
msr/include/msrio.h
msr/include/msr.h
msr/include/pentium.h
msr/include/pentium.c
msr/include/pentium.o
msr/monitor/Makefile
msr/monitor/monitor.h
msr/monitor/monitor.c
msr/monitor/buffer.h
msr/monitor/error.h
msr/monitor/error.c
msr/monitor/sync.h
msr/monitor/sync.c
msr/monitor/monitor