Page 3 of 4

Re:CPU Identification For OS Developers...

Posted: Tue Oct 10, 2006 8:44 pm
by Brynet-Inc
Wow, Thanks smiddy..

Also I'm releasing another patch, It includes some additional features for Intel CPU detection.

Brand Number and Information..

I had started this before but never finished it. :-*

Re:CPU Identification For OS Developers...

Posted: Tue Oct 10, 2006 10:13 pm
by smiddy
No sweat! A cursory look at CPUID from http://www.sandple.org/ seems to have quite a few 64-bit CPUs there, along with a few obscure CPUs from other vendors than Intel and AMD.

Oh, it is also good to look at the manufactures website for hidden features associated with CPUID that only their processor does, if I recall right. It has been over a year since I last worked on my own CPUID routine.

;D

Re:CPU Identification For OS Developers...

Posted: Wed Oct 11, 2006 6:09 am
by Combuster
Brynet-Inc wrote: And is anyone at all interested in classic Cyrix CPU detection support?
Cyrixes are rare nowadays, and even i dont have one. so having it is pretty much a feature for nerds or scrooges. But then againg cyrix has had his share and there are probably still people trying to run someone's os on that platform.

The biggest problem with cyrix is that only the 6x86 series and later (which is only the MediaGX afaik) have cpuid support enabled by default. On other systems, you have to enable that via a set of MSRs, which would further limit the cpuid only detection to these two series. Basically you can only detect a third of the cyrix chips without additional asm-level code.

But then again, we are all crazy enough to be osdeving in the first place so why not ;)

Re:CPU Identification For OS Developers...

Posted: Wed Oct 11, 2006 7:28 am
by Brendan
Hi,
Combuster wrote:
Brynet-Inc wrote:And is anyone at all interested in classic Cyrix CPU detection support?
Cyrixes are rare nowadays, and even i dont have one. so having it is pretty much a feature for nerds or scrooges. But then againg cyrix has had his share and there are probably still people trying to run someone's os on that platform.
For "pentium compatible" CPUs, I've got about 3 Cyrix and 2 AMD...

For other CPU manufacturers, VIA and Transmeta are still making/selling 80x86 compatible CPUs. Even though these products are more often used in embedded systems, they can be found in normal desktop/laptop systems too.
Combuster wrote:The biggest problem with cyrix is that only the 6x86 series and later (which is only the MediaGX afaik) have cpuid support enabled by default. On other systems, you have to enable that via a set of MSRs, which would further limit the cpuid only detection to these two series. Basically you can only detect a third of the cyrix chips without additional asm-level code.

But then again, we are all crazy enough to be osdeving in the first place so why not ;)
If you don't have special detection code for Cyrix chips, then some other software may have enabled CPUID on these chips (e.g. BIOS). In any case, your OS may crash because of un-detected bugs in these CPUs. For example, any attempt to access CR4 in a "pentium compatible" Cyrix chip causes an exception (can't remember if it's a general protection fault or an undefined opcde). If CPUID was enabled then some Cyrix chips return ECX = 'tead' when CPUID is used with eax = 1, which can cause the OS to think it supports all sorts of much more recent features - it corresponds to the following features: SSE3, Intel's hardware virtualisation (VMX), cache context ID, the CMPXCHG16B instruction and task priority disabling, and will also make a mess features added in the future.

In general (IMHO), an OS designer has 4 choices:
  • - write unreliable software.
    - never support any features that are detected via. CPUID
    - never allow any code to use CPUID directly, except for your detection code, and try to fix all of the bugs within your detection code.
    - create a list of exactly which CPUs your OS should work on, and make sure end-users check this list.
The first 2 options are perfectly fine for a hobby/educational OS...


Cheers,

Brendan

Re:CPU Identification For OS Developers...

Posted: Wed Oct 11, 2006 7:49 am
by Brendan
Hi again,

While I'm at it, I thought it'd be a good idea to show how to detect these Cyrix chips...

The general steps would be to try CPUID first, and if it's not supported check if the CPU is a Cyrix, if it is a Cyrix try to enable the CPUID instruction and then try CPUID again.

Hopefully everyone knows how to detect if CPUID is supported (see if the "ID" flag in the eflags register can be modified), so I'll skip that.

Code: Select all

;Check if CPU is a Cyrix with CPUID disabled.
;_______________________________________________________________________________

   clr ax
   sahf
   mov  ax,5
   mov  bx,2
   div  bl
   lahf
   cmp  ah,2         ;Is it Cyrix?
   jne .is486         ; no, must be 80486

;Cyrix Detected - Try To Enable CPUID
;_______________________________________________________________________________

;Preset CPU vendor string to 'CyrixInstead' in case CPUID not supported

   mov dword [gs:edi+CPUdataStruct.vendorString],'Cyri'
   mov dword [gs:edi+CPUdataStruct.vendorString+4],'xIns'
   mov dword [gs:edi+CPUdataStruct.vendorString+8],'tead'

;Get processor ID

   pushfd            ;Save eflags
   cli            ;Disable interrupts
   mov al,0xFE
   out 0x22,al         ;Address = device ID register 0
   clr ebx
   in al,0x23         ;al = device ID register 0
   mov bh,al         ;bh = device ID register 0
   mov al,0xFF
   out 0x22,al         ;Address = device ID register 1
   in al,0x23         ;al = device ID register 1
   popfd            ;Restore original eflags (and interrupts)

   mov bl,al         ;bh = device ID register 1
   cmp bh,0x20         ;Is it a 486?
   jb .oldCyrix         ; yes, no CPUID anyway

;Try to enable CPUID

   pushfd            ;Save eflags
   cli            ;Disable interrupts
   mov al,0xC3
   out 0x22,al         ;Address = config register 3
   in al,0x23         ;al = config register 3
   mov ch,0x0F         ;ch = config register 3 mask
   mov cl,al         ;cl = original config register 3 contents
   and ch,al
   or ch,0x10
   mov al,0xC3
   out 0x22,al         ;Address = config register 3
   mov al,ch
   out 0x23,al         ;Set new config register 3 (enable config access)

   mov al,0xE8
   out 0x22,al         ;Address = config register 4
   mov ch,0x80         ;ch = CPUID enable bit
   in al,0x23         ;al = current config register 4 contents
   or ch,al         ;ch = config register 4 with CPUID enable bit
   mov al,0xE8
   out 0x22,al         ;Address = config register 4
   mov al,ch         ;al = config register 4 with CPUID enable bit
   out 0x23,al         ;Set CPUID enabled bit

   mov al,bh         ;al = device ID register 0
   and al,0xF0
   cmp al,0x30         ;Is it an early 6x86?
   jne .not6x86         ; no

   mov al,0xE9
   out 0x22,al         ;Address = config register 5
   mov ch,0xFD         ;ch = mask
   in al,0x23         ;al = config register 5
   and ch,al         ;ch = fixed config register 5
   mov al,0xE9
   out 0x22,al         ;Address = config register 5
   mov al,ch         ;al = fixed config register 5
   out 0x23,al         ;Set new config register 5 (attempt to fix CPU bug)
.not6x86:
   mov al,0xC3
   out 0x22,al         ;Address = config register 3
   mov al,cl
   out 0x23,al         ;Restore old config register 3 (disable config access)

;Recheck CPUID presence
I wrote this based on the what little documentation I could find (mostly an original IBM application note) and some information from Ralph Brown's Interrupt list concerning I/O ports 0x22 and 0x23. I've tested it on my machines (both Cyrix and non-Cyrix), and it *seems* to work perfectly...


Cheers,

Brendan

Re:CPU Identification For OS Developers...

Posted: Wed Oct 11, 2006 12:15 pm
by Brynet-Inc
Wow, I went through it this morning and noticed a few unused variables in the code, Cleaned up..

Thanks Smiddy/Brendan... ;)

Those interested in Cyrix support for models MediaGX, 6x86, 6x86/MX or BXm..

A friend of mine sent me patches to support Cyrix chips, I don't have any so I can't verify this works so I'm not including it in the main file..

Declare int do_cyrix(void); at the top of the file..

In the detect_cpu() function add:

Code: Select all

case 0x69727943: /* Cyrix Magic Code */
do_cyrix();
break;
Then add the do_cyrix() function..

Code: Select all

int do_cyrix(void)
{
        printf("Cyrix-specific functions:\n");
        unsigned long eax, unused;
        int model, family, stepping, reserved;
        cpuid(1, eax, unused, unused, unused);
        model = (eax >> 4) & 0xf;
        family = (eax >> 8) & 0xf;
        stepping = eax & 0xf;
        reserved = eax >> 12;
        printf("Family: %d Model: %d [", family, model);
        switch(family)
        {
                case 4:
                switch(model)
                {
                        case 4:
                        printf("MediaGX");
                        break;
                }
                break;
                case 5:
                switch(model)
                {
                        case 2:
                        printf("6x86");
                        break;
                        case 4:
                        printf("BXm");
                        break;
                }
                break;
                case 6:
                switch(model)
                {
                        case 0:
                        printf("6x86/MX");
                        break;
                }
                break;
        }
        printf("Stepping %d\n", stepping);
        printf("Reserved %d\n", reserved);
}

Posted: Wed Oct 18, 2006 2:42 am
by Brynet-Inc
Now that the topics have been moved over to OSDev the attachments were not, So I edited the main topic to show a link to the latest source code :)

Enjoy MT/OSDev users...

Posted: Sat Oct 21, 2006 10:21 pm
by chase
How would you feel about moving this into the OSDev Wiki?
I just modified the wiki to support uploading of files.

I read though all of this thread and at some point everyone will need to agree on coding style/compilers/etc but thats a separate discussion that we'll start once a couple of more MT people have a chance to move over.

Little bit more on topic, I have a Transmeta system that I still use and I think I have some Cyrix 5x86 cpus and motherboards in a closet somewhere.

Posted: Sun Oct 22, 2006 12:19 am
by Brynet-Inc
chase wrote:How would you feel about moving this into the OSDev Wiki?
I just modified the wiki to support uploading of files.

I read though all of this thread and at some point everyone will need to agree on coding style/compilers/etc but thats a separate discussion that we'll start once a couple of more MT people have a chance to move over.

Little bit more on topic, I have a Transmeta system that I still use and I think I have some Cyrix 5x86 cpus and motherboards in a closet somewhere.
Well if you wish to list this on the Wiki your welcome, I've never really done any Wiki stuff so I wouldn't know where to start :wink:

If your willing to check out Transmeta systems your more then welcome :)

Compile and run this on the Transmeta to find the Magic Code for dealing with that specific CPU manufacture.

Code: Select all

#include <stdio.h>
#define cpuid(in, a, b, c, d) asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));

int main(void)
{
        unsigned int ebx, unused;
        cpuid(0, unused, ebx, unused, unused);
        printf("0x%x\n", ebx);
        return 0;
}

Posted: Thu Oct 26, 2006 8:01 am
by Brynet-Inc
Thanks to chase the forum has file uploading support, I uploaded cpuid-clean.c.

It's on the first post. 8)

Posted: Thu Oct 26, 2006 10:11 am
by inflater
2 brynet-inc:

Sorry for little "psychological intoleration" in "Mouse problems" topic.
I had for that day too much things to do... :P

inflater

Posted: Sat Oct 28, 2006 1:47 pm
by Brynet-Inc
Hey, I've updated CPUID, Including a few variables renames with more detailed names and also support for detecting the temperature sensing diode on a few AMD CPU's :)

I wrote this is for detecting the Maximum Physical and Linear Address Size on AMD CPU's..

Code: Select all

#include <stdio.h>
#define cpuid(in,a,b,c,d) asm("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));

int main(void)
{
	unsigned long unused, eax;
	cpuid(0x80000008, eax, unused, unused, unused);
	printf("Maximum Linear Address: %ld\n", (eax >> 8) & 0xff);
	printf("Maximum Physical Address: %ld\n", eax & 0xff);
}

Posted: Wed Nov 15, 2006 11:10 pm
by Brynet-Inc
Thanks to quok of this forum Intel CPU brand detection has been improved significantly, It now successfully checks to make sure the CPU even supports the brand string feature and now reports even more detailed brand information.

The main topic has been edited with the new file.

Thanks quok :)

Posted: Wed Nov 15, 2006 11:30 pm
by quok
Here's the patch I gave to Brynet for the Intel brand detection update. If anyone wants to just download this and apply it, it applies pretty easily with the command (after unzipping of course):

Code: Select all

patch -p0 -i cpudet-better_intel_brand_detection.patch cpudet-clean.c

Posted: Wed Nov 15, 2006 11:46 pm
by Brynet-Inc
Those of you may want to study his patch at least, Some of his comments didn't make it into my alterations.. (Sorry lol..)

Anyway, Thanks.