//------------------------------------------------------------------- // mymtrr.c // // This module creates a pseudo-file named '/proc/mymtrr' that // lets users see the current contents of those Model-Specific // Registers which pertain to Memory Type and Range Registers. // (These registers control configuration of 'memory-cacheing' // attributes for up to 96 distinct regions of the processor's // physical address space, as described in volume III of Intel // Developer's Manual for the Pentium family of processors.) // // Our initial motivation for developing this tool was to help // determine why our current ATI Radeon X300 graphics adapters // were exhibiting unusually slow memory-to-memory copying for // regions in the video display-memory range, but this tool is // potentially useful as a more general diagnostic utility. // // NOTE: Written and tested using Linux kernel version 2.6.12. // // programmer: ALLAN CRUSE // written on: 10 NOV 2005 //------------------------------------------------------------------- #include // for init_module() #include // for create_proc_read_entry() struct reginfo { int id; char *name; }; struct reginfo msrlist[] = { { 0x200, "MTRRphysBase0" }, { 0x201, "MTRRphysMask0" }, { 0x202, "MTRRphysBase1" }, { 0x203, "MTRRphysMask1" }, { 0x204, "MTRRphysBase2" }, { 0x205, "MTRRphysMask2" }, { 0x206, "MTRRphysBase3" }, { 0x207, "MTRRphysMask3" }, { 0x208, "MTRRphysBase4" }, { 0x209, "MTRRphysMask4" }, { 0x20A, "MTRRphysBase5" }, { 0x20B, "MTRRphysMask5" }, { 0x20C, "MTRRphysBase6" }, { 0x20D, "MTRRphysMask6" }, { 0x20E, "MTRRphysBase7" }, { 0x20F, "MTRRphysMask7" }, { 0x250, "MTRRfix64K_00000" }, { 0x258, "MTRRfix16K_80000" }, { 0x259, "MTRRfix16K_A0000" }, { 0x268, "MTRRfix4K_C0000" }, { 0x269, "MTRRfix4K_C8000" }, { 0x26A, "MTRRfix4K_D0000" }, { 0x26B, "MTRRfix4K_D8000" }, { 0x26C, "MTRRfix4K_E0000" }, { 0x26D, "MTRRfix4K_E8000" }, { 0x26E, "MTRRfix4K_F0000" }, { 0x26F, "MTRRfix4K_F8000" }, { 0x2FF, "MTRRdefType" }, { 0x0FE, "MTRRcap" } }; const int n_msrs = sizeof( msrlist ) / sizeof( struct reginfo ); char modname[] = "mymtrr"; char legend1[] = "\nIntel P6 Memory Type and Range Registers"; char legend2[] = "\n----------------------------------------"; char legend3[] = "\n%08X: %08X%08X %s "; int my_proc_read( char *buf, char **start, off_t off, int count, int *eof, void *data ) { int i, len = 0; len += sprintf( buf+len, legend1 ); len += sprintf( buf+len, legend2 ); for (i = 0; i < n_msrs; i++) { char *name = msrlist[ i ].name; int reg = msrlist[ i ].id, val_hi, val_lo; __asm__ __volatile__ ( "movl %2, %%ecx \n" \ "rdmsr \n" \ "movl %%eax, %1 \n" \ "movl %%edx, %0 " : "=m" (val_hi), "=m" (val_lo) : "m" (reg) : "ecx", "eax", "edx" ); len += sprintf( buf+len, legend3, reg, val_hi, val_lo, name ); } len += sprintf( buf+len, "\n\n" ); return len; } int init_module( void ) { printk( "<1>\nInstalling \'%s\' module\n", modname ); create_proc_read_entry( modname, 0, NULL, my_proc_read, NULL ); return 0; // SUCCESS } void cleanup_module( void ) { remove_proc_entry( modname, NULL ); printk( "<1>Removing \'%s\' module\n", modname ); } MODULE_LICENSE("GPL");