Disable interrupts from user space

Example Code





int main (int argc, char **argv)
{
    iopl(3);        // Go to the privileged level

    asm("cli");  // Disable interrupts

    /* Code goes here  (Make sure this part is as small as possible) */

    asm("sti");  // Enable interrupts
}


IMPORTANT: This code should be run with superuser privileges

The header file 'sys/io.h' must be included for iopl

Measuring Timing Accurately on Intel Processors

This blog shows how timing measurements for C code can be made accurately. The output is in clock cycles.


1. The timing is measured by using the 'RDTSC' instruction, which returns the processors timestamp value. This value is maintained in a register and incremented at every clock cycle.

2. However, due to the out-of-order execution of the processor, it is not certain when the RDTSC instruction is actually executed. Therefore, we flush the processor's pipeline before and after invoking RDTSC. This ensures that every measurement begins in the same state. The flushing of the pipeline is done by the CPUID instruction.

The code snippet:


unsigned int timestamp(void)
{
    unsigned int bottom;
    unsigned int top;
    asm volatile("xorl %%eax,%%eax\n cpuid \n" ::: "%eax", "%ebx", "%ecx", "%edx"); // flush pipeline
    asm volatile("rdtsc\n" : "=a" (bottom), "=d" (top) );                           // read rdtsc
    asm volatile("xorl %%eax,%%eax\n cpuid \n" ::: "%eax", "%ebx", "%ecx", "%edx"); // flush pipeline again
    return bottom;
}


int main()
{
    unsigned int t1, t2, to1, to2, tover;

    /* Measure the overhead first */ 
    to1 = timestamp();
    to2 = timestamp();
    tover = to2 - to1;
   

    t1 = timestamp();
    /**** Code to be measured goes here *****/
    t2 = timestamp();
    printf("Time Taken (in clock cycles) : %ul\n", (t2 - t1 - tover));
}

pfmon on Ubuntu 9.04

In this blog, I write about my experiences getting pfmon to run on my system (Intel Core 2 running Ubuntu 9.04).


1. The first step is to patch the kernel with perfmon2.
  • I First checked the most recent kernel patch that is supported by perfmon2. You will be able to find this in http://perfmon2.sourceforge.net. In my case it was 2.6.28 2nd release.
  • I installed the kernel (2.6.28) the old fashioned way (without git). I first installed the necessary packages required for building kernels, and then downloaded the kernel with instructions from https://help.ubuntu.com/community/Kernel/Compile.
  • I then patched the kernel with the perfmon2 patch I downloaded. Instructions for patching the kernel were from http://www.linuxheadquarters.com/howto/tuning/kernelpatch.shtml. There was a bit of a problem with the patching since I used a kernel from the Ubuntu distribution and not the original kernel.org kernel (for which the patch was made). These problems were easily rectified by manually (and carefully) patching the files which gave errors.
  • ... and rebooted  to the new kernel :)

2. The second step is to install libpfm and pfmon
  •  Although Ubuntu's package manager supported it. The versions of pfmon present in Ubuntu conflicted with the kernel patch I had installed. So when I ran the command
                   $ pfmon date
         I got the error

                     can't create perfmon context: Invalid argument(22)

  • I then realized that for the 2.6.28 patch, I needed libpfm 3.8 and pfmon 3.8. So I downloaded these from  http://perfmon2.sourceforge.net and installed them. First installed the libpfm and then the pfmon.
  • It now works :) :). The command '$pfmon date' gives
                     Wed Apr 28 13:53:52 IST 2010
                     760973 UNHALTED_CORE_CYCLES

Programming Intel's Model-Specific Registers (MSRs)


Model (or sometimes called Machine) Specific Registers (MSRs) are a useful tool during debugging to determine the working of the processor. They can also be used to control the functioning of the processor such as the working of the cache memories, branch prediction logic etc.


Accessing MSRs

To access the MSR registers, there are two requirements.
  1. The kernel must support it.
  2. A user space application must be required to communicate with the kernel
The MSR Driver
For the Linux kernel, a module msr is to be present.

To check if your kernel has MSR support built in :

            $ cat /boot/config-2.6.28-18-generic | grep MSR
               CONFIG_X86_MSR=m 

On my Ubuntu 9.04, the MSR is a module. I added it to
the kernel with the command:
            
           $ sudo modprobe msr

Inserting the module would create the device files /dev/cpu/_processor_number_/msr. There would be one msr device for each processor.

User Space Access (msr-tools)
msr-tools can be downloaded from the kernel.org site http://www.kernel.org/pub/linux/utils/cpu/msr-tools/msr-tools-1.1.2.tar.bz2. If you are using Ubuntu, msr-tools can be installed using the package manager.

msr-tools have two executables:
rdmsr : This is used to read an MSR register.

            $ sudo rdmsr 0x198 
               6160b2406000b24       

wrmsr : This is used to write to an MSR register
  
            $ sudo wrmsr 0x198 6160b2406000b24



The MSR Registers
The MSR registers for the Intel Processor is present in the Appendix B of Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide



References
  1. http://blogs.koolwal.net/2009/09/19/howto-using-cpu-msr-tools-rdmsrwrmsr-in-debian-linux/

Followers