clock rate probing for x86

Stephan Meyer (sensei@munich.netsurf.de)
Tue, 28 Jan 1997 11:30:32 +0100 (MET)


[this is my first attempt on hacking the kernel, so please be tolerant :)]

Anyway, this patch against kernel 2.0.28/2.1.23 adds clock rate probing to
the linux kernel. An Intel x86 compatible processor with the cpuid and
rdtsc instructions is needed. This adds an entry "clock_rate" to
/proc/cpuinfo. The code checks if the requirements are met before sending
386/486 processors to nirvana.

Please try this.

Exactly how bad is my coding style?
Are the jiffies reliable?
Should the clock rate rather be probed along with the BogoMips at system
startup and stored somewhere?

Cheers, Stephan

Sample output of "cat /proc/cpuinfo" :
processor : 0
cpu : 586
model : Pentium 75+
clock_rate : 120 MHz
vendor_id : GenuineIntel
stepping : 11
fdiv_bug : no
hlt_bug : no
fpu : yes
fpu_exception : yes
cpuid : yes
wp : yes
flags : fpu vme de pse tsc msr mce cx8
bogomips : 48.03

context patch follows:

------------------- cut here
*** setup.c.old Mon Jan 27 18:32:56 1997
--- setup.c Tue Jan 28 11:12:34 1997
***************
*** 8,13 ****
--- 8,19 ----
* This file handles the architecture-dependent parts of initialization
*/

+ /*
+ * processor clock rate probing code added
+ * needs cpuid and rdtsc instructions
+ * 01/28/97 by Stephan Meyer <Stephan.Meyer@munich.netsurf.de>
+ */
+
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
***************
*** 203,208 ****
--- 209,251 ----
request_region(0xc0,0x20,"dma2");
request_region(0xf0,0x10,"npu");
}
+
+ static char * getmhz()
+ {
+ unsigned long int la,ha,lb,hb,c,j,q,r;
+ static char buffer[20];
+ if (!have_cpuid) {
+ strcpy(buffer,"no_tsc");
+ return buffer;
+ }
+ __asm__ __volatile__ (
+ "movl $1,%%eax
+ cpuid"
+ :"=d" (c)
+ :
+ :"%eax","%ebx","%ecx","%edx");
+ if ((c & 0x10)==0) {
+ strcpy(buffer,"no_tsc");
+ return buffer;
+ }
+ j=jiffies;
+ for (;j==jiffies;); j=jiffies;
+ __asm__ __volatile__ (
+ "rdtsc"
+ : "=a" (la),"=d" (ha)
+ :
+ : "%eax","%edx");
+ for (;j==jiffies;);
+ __asm__ __volatile__ (
+ "rdtsc"
+ : "=a" (lb),"=d" (hb)
+ :
+ : "%eax","%edx");
+ c=lb-la; if (ha!=hb) c+=UINT_MAX;
+ q=c/10000; r=c%10000; if (r>=5000) q++;
+ sprintf(buffer,"%i MHz",(int) q);
+ return buffer;
+ }

static const char * i486model(unsigned int nr)
{
***************
*** 287,298 ****
--- 330,343 ----
len += sprintf(buffer+len,"processor\t: %d\n"
"cpu\t\t: %c86\n"
"model\t\t: %s\n"
+ "clock_rate\t: %s\n"
"vendor_id\t: %s\n",
CPUN,
CD(x86)+'0',
CD(have_cpuid) ?
getmodel(CD(x86), CD(x86_model)) :
"unknown",
+ CD(getmhz()),
CD(x86_vendor_id));

if (CD(x86_mask))
--------- cut here

-----------------------------------------------
Stephan Meyer
+49-89-4301114
Stephan.Meyer@munich.netsurf.de
http://fatman.mathematik.tu-muenchen.de/~meyer/
-----------------------------------------------