Messages in this thread Patch in this message | | | From | "Nicholas J. Leon" <> | Date | Tue, 23 Dec 1997 13:50:02 -0500 (EST) | Subject | [PATCH] Intel clock speed detection |
| |
Fellow kernel enthusiasts -
I've been playing with routines to determine actual cpu speed on Intel chips; hoping to replace the "75+" notation with something accurate.
Using some assembly routines from a patch I acquired a few months ago, whose author I have completely forgotten, I've made some preliminary patches against 2.1.75. Here is what I did:
. added a field called "x86_mhz" to cpuinfo_x86 . added a function called "get_cpu_speed" to setup.c . calling get_cpu_speed from identify_cpu() in setup.c . added reporting of the speed to print_cpu_info() and get_cpuinfo() in setup.c
Here are the problems I know I haven't addressed:
. does my mhz detection routine work reliably (ie, at all) with all non-intel cpu's? . what about SMP machines? . slight variation of reported mhz (132 vs 133) . struct cpu_model_info now has redundant elements of "Pentium" (since I removed the 60/66, 75+). I'm not sure how these are referenced in the first place, so I didn't compact them together (as they should be).
The first I am hoping that some people out there will try my patch on their AMD and Cyrix systems and let me know. The second, uhhhhh, well, I'm over my head with this one. I would certainly appreciate any and all help that might come my direction. Regardless of knowledge, though, I have no practical way of testing SMP's reaction to my patch. So I must rely on others for this.
I know that in the past, Linus has refused to include clock speed detecting into the kernel. From what I understand, the original patch did the calculations on the fly when you examined /proc/cpuinfo and this was the reason for the refusal. My patch doesn't. It calculates the rate upon boot and stores the information into cpuinfo_x86. Hopefully, this will allow its inclusion into the mainstream kernel once all the issues have been taken care of.
Please, take the time and look at what I've done. I know its not anything amazing, but since the kernel isn't written in Perl, there's not a lot I can contribute :) This, however, might be one of those things I _can_ do.
Thank you for your time!
[ patch attached ]
___________________________________________________________________________
simple is elegant nicholas@binary9.net ___________________________________________________________________________ diff -Nur linux.75.prist/Makefile linux/Makefile --- linux.75.prist/Makefile Sun Dec 21 20:58:14 1997 +++ linux/Makefile Mon Dec 22 20:22:40 1997 @@ -11,7 +11,7 @@ # # NOTE! SMP is experimental. See the file Documentation/SMP.txt # -SMP = 1 +#SMP = 1 # # SMP profiling options # SMP_PROF = 1 diff -Nur linux.75.prist/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- linux.75.prist/arch/i386/kernel/setup.c Sun Dec 21 20:27:18 1997 +++ linux/arch/i386/kernel/setup.c Tue Dec 23 13:39:33 1997 @@ -323,6 +323,38 @@ c->x86_vendor = X86_VENDOR_UNKNOWN; } +__initfunc(int get_cpu_speed(void)) +{ + unsigned long int a,b,j,q; + + __asm__ __volatile__ ( + "movl $1,%%eax + cpuid" + :"=d" (a) + : + :"%eax","%ebx","%ecx","%edx"); + + if ((a & 0x10)==0) { + return 0; + } + j=jiffies; + for (;j==jiffies;); j=jiffies; + __asm__ __volatile__ ( + "rdtsc" + : "=a" (a) + : + : "%eax","%edx"); + for (;j==jiffies;); + __asm__ __volatile__ ( + "rdtsc" + : "=a" (b) + : + : "%eax","%edx"); + q=((b-a)+(500000/HZ))/(1000000/HZ); + + return q; +} + struct cpu_model_info { int vendor; int x86; @@ -334,9 +366,9 @@ { "486 DX-25/33", "486 DX-50", "486 SX", "487 DX", "486 DX/2", "486 SL", "486 SX/2", NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL }}, { X86_VENDOR_INTEL, 5, - { "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75+", + { "Pentium A-step", "Pentium", "Pentium", "OverDrive PODP5V83", "Pentium MMX", NULL, NULL, - "Mobile Pentium 75+", "Mobile Pentium MMX", NULL, NULL, NULL, + "Mobile Pentium", "Mobile Pentium MMX", NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_INTEL, 6, { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II", NULL, @@ -397,6 +429,8 @@ strcpy(c->x86_model_id, p); else sprintf(c->x86_model_id, "%02x/%02x", c->x86_vendor, c->x86_model); + + c->x86_mhz=get_cpu_speed(); } static char *cpu_vendor_names[] __initdata = { @@ -419,6 +453,9 @@ else printk("%s", c->x86_model_id); + if (c->x86_mhz) + printk(" %i Mhz",c->x86_mhz); + if (c->x86_mask) printk(" stepping %02x", c->x86_mask); @@ -450,10 +487,12 @@ p += sprintf(p, "processor\t: %d\n" "cpu family\t: %c\n" "model\t\t: %s\n" + "clock speed\t: %d Mhz\n" "vendor_id\t: %s\n", n, c->x86 + '0', c->x86_model_id[0] ? c->x86_model_id : "unknown", + c->x86_mhz, c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown"); if (c->x86_mask) { if (c->x86_vendor == X86_VENDOR_CYRIX) diff -Nur linux.75.prist/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- linux.75.prist/include/asm-i386/processor.h Sun Dec 21 20:27:18 1997 +++ linux/include/asm-i386/processor.h Tue Dec 23 13:14:43 1997 @@ -33,6 +33,7 @@ int fdiv_bug; int f00f_bug; unsigned long loops_per_sec; + u16 x86_mhz; }; #define X86_VENDOR_INTEL 0 | |