VOGONS


Analyzing old CPUID code

Topic actions

First post, by Disruptor

User metadata
Rank Oldbie
Rank
Oldbie
debs3759 wrote:

I just sent you my CPUID code (it stops shortly after x64 cpus came out, has a lot of old data). It's public domain with a copyright, so can be freely shared and used as long as I am given credit for code I supply.

I also have data relating to various 808x versions that is not yet in the files, if you need it.

Thanks Debbie for sharing that code.

After a first view on it, i was overwhelmed because it has show me that it is much more work than I have expected to achieve that results .
My pal mkarcher has commented "solid work". I fully agree to that.

I'll do some tests later.

I'll examine the detection of both CPUID and CPUID-less 486.

I know that the Am486 change their identifier when changing the jumpers from 3x to 4x or from 3x to 2x and when changing from write-back to write through.
But I'll inspect my Am486 DX4 NV8T too.

I also wonder how many different kinds of Am486 exist. WT/WB, 8K/16K L1, With/Without FPU, With/Without Intel ICE, 2x 3x 4x Multiplicator, Revisions/Steppings, Clock frequency

Last edited by Disruptor on 2023-04-12, 13:13. Edited 1 time in total.

Reply 1 of 27, by debs3759

User metadata
Rank Oldbie
Rank
Oldbie

Thanks. I'll appreciate if you can post the output for any CPUs you test with it.

See my graphics card database at www.gpuzoo.com
Constantly being worked on. Feel free to message me with any corrections or details of cards you would like me to research and add.

Reply 2 of 27, by Disruptor

User metadata
Rank Oldbie
Rank
Oldbie

Okay, 1st test with my Saturn II board (ASUS PCI/I-486SP3) has failed. This board is too smart for your reset method 😀 and finds the BIOS no matter how A20M is set.

Reply 3 of 27, by debs3759

User metadata
Rank Oldbie
Rank
Oldbie

Does it not find the ID any other way? Such as from the BIOS?

It's difficult on some systems, but I didn't have enough boards when I wrote it to test as thoroughly as I hope to when I finish organising things in my new home 😀

See my graphics card database at www.gpuzoo.com
Constantly being worked on. Feel free to message me with any corrections or details of cards you would like me to research and add.

Reply 4 of 27, by Disruptor

User metadata
Rank Oldbie
Rank
Oldbie

No, but at least your code does not crash. Solid work!
Stay tuned!

Reply 5 of 27, by Disruptor

User metadata
Rank Oldbie
Rank
Oldbie

Installed: Am386DX 40, Cyrix FasMath CX-83D87-40-GP

Compatibility: 386
ID method: Reset
CPU Vendor: Intel/AMD or compatible
Processor ID: 0308
Model: 386DX
Stepping/Revision: D1,D2,Ex,Fx (intel) or B (AMD)

Edit: line with FPU removed, as there is obviousely no FPU detection code included

Last edited by Disruptor on 2023-04-13, 17:27. Edited 2 times in total.

Reply 6 of 27, by debs3759

User metadata
Rank Oldbie
Rank
Oldbie

Thanks.

I never tried writing code to detect what fpu was present. It was never written as release code, I merely offered the CPU detection code for anyone who wants it. I'll have to see at some point how to detect what fpu is present, not sure how to go about that. Will have to do some research on that.

See my graphics card database at www.gpuzoo.com
Constantly being worked on. Feel free to message me with any corrections or details of cards you would like me to research and add.

Reply 7 of 27, by Disruptor

User metadata
Rank Oldbie
Rank
Oldbie

Debbie, it's just a test.
And I know what a version number of 0.1 has to say. 😀
We just had similar thoughts with Jan (CUPID) some weeks ago.

With your code it is easier to help, because we have the source.
Ok, now I see, FPU check is not implemented at all. Sorry.

Reply 8 of 27, by Deunan

User metadata
Rank Oldbie
Rank
Oldbie
Disruptor wrote on 2023-04-13, 09:03:

Processor ID: 0308
Model: 386DX
Stepping/Revision: D1,D2,Ex,Fx (intel) or B (AMD)

What exactly is B-step for AMD? What other steppings are there and how to tell them apart?
Asking because I've seen this being reported by various programs and I always wondered where this piece of info came from, what datasheet or any other official AMD document.

Reply 9 of 27, by debs3759

User metadata
Rank Oldbie
Rank
Oldbie

I found 4 sources that detailed this stepping, but don't have a full list of errata. Sources include Ralf Brown's interrupt list, Grzegorz Mazur, sandpile.org and Chiplist.

See my graphics card database at www.gpuzoo.com
Constantly being worked on. Feel free to message me with any corrections or details of cards you would like me to research and add.

Reply 10 of 27, by Deunan

User metadata
Rank Oldbie
Rank
Oldbie

Thanks. I went through some of these to refresh my memory but I still don't see any actual official info, just guesswork and copies of copies of pre-existing code and ideas.
For example RBIL (at least the version I have) makes no mention of AMD 386 ID's at all, just the Intel ones. Both it and Debs cpuid.txt claim that 0303 ID is valid for B0 step, which I seriously doubt considering Intel came forward with this particular information to help distinguish B0 and B1 (which was way less broken).
Grzegorz Mazur webpage on the other hand omits B0 (why?) and also claims 0300 is a code for A step - is it really? Was the ID in DX on reset already present in the A step? There's no actual proof of that AFAIK. Could be pure guesswork. Also it calls AMD chips "rev A/B" not "step".

I know I'm nitpicking but it annoys me that each new program that adds 386 and early 486 identification simply copies the existing info, making it look more and more like "common knowledge" - and I have my doubts about it being any sort of actual knowledge at all. Not pointing fingers, just making a statement.

Reply 11 of 27, by mkarcher

User metadata
Rank l33t
Rank
l33t
debs3759 wrote on 2023-04-12, 21:54:

Does it not find the ID any other way? Such as from the BIOS?

It's difficult on some systems, but I didn't have enough boards when I wrote it to test as thoroughly as I hope to when I finish organising things in my new home 😀

That board uses an AWARD BIOS (rev 4.50 or 4.51). This kind of BIOS is very widespread and unfortunately doesn't store the DX-after-reset value anywhere, so it can't provide any API to retrieve it. As the A20M method doesn't work too (there is a FAR JMP instruction at FFEFFFF0h, so obviously A20 isn't decoded when accessing the BIOS at "end of address space"), your code implements no way to get DX after reset. There is another common way to get DX-after-reset, though, that is not yet implemented in your CPUID code: They claim that certain BIOSes do not disrupt the DX value on certain shutdown codes - though I don't have the detail at hand at the moment. Typical shutdown codes that are useful for program resumption after reset are 04,05,09 and 0A, and I've seen you use one of them as fallback layer if the reset for some reason does manage to get into the BIOS code.

My plan is to extend the CPU ID probing by validating whether resumption via shutdown code preserves DX, and in that case, do a reset with A20 enabled and the correct shutdown code, and not reject the DX value as you currently do when the shutdown-code resumption safety net is triggered. I intend to validate the DX preservation property by adding a 4G code segment descriptor with 4G limit and base 0FFFFF000h, so jumping to offset 0FFF0h provides the same CPU state as after a reset. I then intend to jump there two times with different test values in DX and check whether they are preserved. If yes, DX is trustworthy even if the RESET is caught by BIOS code.

Reply 12 of 27, by Disruptor

User metadata
Rank Oldbie
Rank
Oldbie

Hi Debbie,
mkarcher has adapted the code so that it will use the 286 reset method on that Saturn II motherboard.
Here are the results:

Cyrix Cx486DX-40 @ 33 MHz
Compatibility : 486
Identification method : Cyrix DIRs
Vendor ID :
CPU Vendor : Cyrix or compatible
Processor ID : 1A04
Processor type :
Family :
Model : 486DX
Stepping/Revision : 1.4
Core/Bus Clock Ratio :

ST 486 DX4 100 in x2 mode, @ 33 MHz
Compatibility : 486
Identification method : Cyrix DIRs
Vendor ID :
CPU Vendor : Cyrix or compatible
Processor ID : 1B36
Processor type :
Family :
Model : 486DX4
Stepping/Revision : 4.6
Core/Bus Clock Ratio :

ST 486 DX4 100 in x3 mode, @ 33 MHz
Compatibility : 486
Identification method : Cyrix DIRs
Vendor ID :
CPU Vendor : Cyrix or compatible
Processor ID : 1F36
Processor type :
Family :
Model : 486DX4
Stepping/Revision : 4.6
Core/Bus Clock Ratio :

Am486 DX4 NV8T 100 -- Warning: same identifier in x2 and x3 mode!
Compatibility : 486
Identification method : Reset/BIOS
Vendor ID :
CPU Vendor : Intel/AMD or compatible
Processor ID : 0432
Processor type :
Family :
Model : 486DX2
Stepping/Revision : A0-A2 (Intel) or Unknown (AMD)
Core/Bus Clock Ratio :

Intel 486 DX 33 SX419
Compatibility : 486
Identification method : Reset/BIOS
Vendor ID :
CPU Vendor : Intel/AMD or compatible
Processor ID : 0404
Processor type :
Family :
Model : 486DX
Stepping/Revision : D0
Core/Bus Clock Ratio :

Show last 48 lines
Intel 486 DX2 66 SX759
Compatibility : 486
Identification method : Reset/BIOS
Vendor ID :
CPU Vendor : Intel
Processor ID : 0433
Processor type :
Family :
Model : 486DX2
Stepping/Revision : B1
Core/Bus Clock Ratio :

Intel 486 DX2 66 SX807
Compatibility : 486
Identification method : CPUID
Vendor ID : GenuineIntel
CPU Vendor : Intel
Processor ID : 0435
Processor type :
Family :
Model : 486DX2
Stepping/Revision : aB0,aC0
Core/Bus Clock Ratio :

Intel 486 DX2 66 SX911
Compatibility : 486
Identification method : CPUID
Vendor ID : GenuineIntel
CPU Vendor : Intel
Processor ID : 0435
Processor type :
Family :
Model : 486DX2
Stepping/Revision : aB0,aC0
Core/Bus Clock Ratio :

Intel ODPR486DX-25 SZ697
Compatibility : 486
Identification method : Reset/BIOS
Vendor ID :
CPU Vendor : Intel
Processor ID : 0433
Processor type :
Family :
Model : 486DX2
Stepping/Revision : B1
Core/Bus Clock Ratio :
Last edited by Disruptor on 2023-04-17, 07:30. Edited 1 time in total.

Reply 13 of 27, by debs3759

User metadata
Rank Oldbie
Rank
Oldbie

Thanks. Can you please send me the modified code, so I can add it to my code?

It all looks how I intended it to. Not sure when/if I'll add clock speed detection.

See my graphics card database at www.gpuzoo.com
Constantly being worked on. Feel free to message me with any corrections or details of cards you would like me to research and add.

Reply 14 of 27, by Scali

User metadata
Rank l33t
Rank
l33t

I wrote some code to detect CPUs and FPUs some years ago, with the non-CPUID stuff based on Intel examples:
https://sourceforge.net/p/cpuinfo/code/ci/def … /tree/CPUInfo.c
It can at the very least detect the family of CPUs and FPUs that do not have CPUID, so it will know if it's a 8086, 286, 386 or 486, or an 87, 287, 387 or 487 respectively (anything above that has CPUID, and guaranteed to have an onboard FPU where the family of of CPU and FPU are the same by default).
So perhaps you can use it to add at least a basic FPU detection routine.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 15 of 27, by debs3759

User metadata
Rank Oldbie
Rank
Oldbie
Scali wrote on 2023-04-17, 08:44:
I wrote some code to detect CPUs and FPUs some years ago, with the non-CPUID stuff based on Intel examples: https://sourceforge. […]
Show full quote

I wrote some code to detect CPUs and FPUs some years ago, with the non-CPUID stuff based on Intel examples:
https://sourceforge.net/p/cpuinfo/code/ci/def … /tree/CPUInfo.c
It can at the very least detect the family of CPUs and FPUs that do not have CPUID, so it will know if it's a 8086, 286, 386 or 486, or an 87, 287, 387 or 487 respectively (anything above that has CPUID, and guaranteed to have an onboard FPU where the family of of CPU and FPU are the same by default).
So perhaps you can use it to add at least a basic FPU detection routine.

Thanks. That'll be helpful, not I just need to find info relating to exactly which fpu it is. There are so many 387 class fpus 😀

See my graphics card database at www.gpuzoo.com
Constantly being worked on. Feel free to message me with any corrections or details of cards you would like me to research and add.

Reply 16 of 27, by Scali

User metadata
Rank l33t
Rank
l33t
debs3759 wrote on 2023-04-17, 11:49:

Thanks. That'll be helpful, not I just need to find info relating to exactly which fpu it is. There are so many 387 class fpus 😀

Yes, that might be difficult. One thing I can think of is to try and use specific instructionset extensions, and see if they generate an invalid opcode exception.
But that won't catch any 'pure' clones that have no extra instructions.

http://scalibq.wordpress.com/just-keeping-it- … ro-programming/

Reply 17 of 27, by mkarcher

User metadata
Rank l33t
Rank
l33t
debs3759 wrote on 2023-04-17, 07:19:

Thanks. Can you please send me the modified code, so I can add it to my code?

It's ready when it's ready, but I will definitely send the proper adjusted code for "Reset-through-BIOS" as a PM to you. In fact, your code already would look at DX (and the upper half of EDX) after a BIOS-supported reset, as the call site of the reset function doesn't care about the carry flag indicating Int6 or BIOS-Resume like reset. But as you explicitly don't attempt to do the reset technique when the BIOS is aliased to 4G-1M, this code hasn't been effective.

I plan to automatically validate the DX-passing capability of the BIOS (and also consider GS as a possible register to find the reset code), but the full implementation isn't done yet.

Reply 18 of 27, by mkarcher

User metadata
Rank l33t
Rank
l33t
mkarcher wrote on 2023-04-13, 20:22:

My plan is to extend the CPU ID probing by validating whether resumption via shutdown code preserves DX, and in that case, do a reset with A20 enabled and the correct shutdown code, and not reject the DX value as you currently do when the shutdown-code resumption safety net is triggered. I intend to validate the DX preservation property by adding a 4G code segment descriptor with 4G limit and base 0FFFFF000h, so jumping to offset 0FFF0h provides the same CPU state as after a reset. I then intend to jump there two times with different test values in DX and check whether they are preserved. If yes, DX is trustworthy even if the RESET is caught by BIOS code.

Well, that plan failed. I can load CS with base FFFF0000 in protected mode, but I need the processor in real mode so it can correctly execute the FAR JMP instruction at the BIOS entry point. This means, I need to switch from protected mode to real mode with CS already loaded. When I load CS with a 16-bit code segment, only the low 16 bits of EIP (that is IP) are in use, so with base FFFF0000, I can only address the last 64KB of address space, which is entirely ROM. I thus can't put my own "go to real mode" code there. It's not that bad, though: If there actually is a FAR JMP at 4GB-16, I can just decode that FAR JMP, and jump directly to that location. This still allows me to test what happens to DX when the reset code is executed.

On the Saturn II board, I get control back with the reset code in the upper half of EDX, whereas the lower half is 0CF8 (the PCI configuration space I/O register). The Award BIOS from a different board uses "mov gs,dx" instead of "ror edx,16". So I implemented probing code that tests whether the DX value when entering the reset vector can be found in DX itself, the upper part of DX or GS in the resume-via-Reset-Type-0Ah handler. This code is working right now, but I am not yet happy with how it interacts with the remaining pieces of the CPU_ID code, so I'm going to refactor that tomorrow.

Reply 19 of 27, by jakethompson1

User metadata
Rank Oldbie
Rank
Oldbie
mkarcher wrote on 2023-04-17, 19:24:
mkarcher wrote on 2023-04-13, 20:22:

My plan is to extend the CPU ID probing by validating whether resumption via shutdown code preserves DX, and in that case, do a reset with A20 enabled and the correct shutdown code, and not reject the DX value as you currently do when the shutdown-code resumption safety net is triggered. I intend to validate the DX preservation property by adding a 4G code segment descriptor with 4G limit and base 0FFFFF000h, so jumping to offset 0FFF0h provides the same CPU state as after a reset. I then intend to jump there two times with different test values in DX and check whether they are preserved. If yes, DX is trustworthy even if the RESET is caught by BIOS code.

Well, that plan failed. I can load CS with base FFFF0000 in protected mode, but I need the processor in real mode so it can correctly execute the FAR JMP instruction at the BIOS entry point. This means, I need to switch from protected mode to real mode with CS already loaded. When I load CS with a 16-bit code segment, only the low 16 bits of EIP (that is IP) are in use, so with base FFFF0000, I can only address the last 64KB of address space, which is entirely ROM. I thus can't put my own "go to real mode" code there. It's not that bad, though: If there actually is a FAR JMP at 4GB-16, I can just decode that FAR JMP, and jump directly to that location. This still allows me to test what happens to DX when the reset code is executed.

On the Saturn II board, I get control back with the reset code in the upper half of EDX, whereas the lower half is 0CF8 (the PCI configuration space I/O register). The Award BIOS from a different board uses "mov gs,dx" instead of "ror edx,16". So I implemented probing code that tests whether the DX value when entering the reset vector can be found in DX itself, the upper part of DX or GS in the resume-via-Reset-Type-0Ah handler. This code is working right now, but I am not yet happy with how it interacts with the remaining pieces of the CPU_ID code, so I'm going to refactor that tomorrow.

It would be really radical and chipset specific, but could you switch the shadowed BIOS from read-only to read-write and temporarily overwrite F000:FFF0 to point somewhere else where you would like to go? As an aside, I wonder how hard of a reset (all the way up to physical reset switch or even power off) is required to force shadowing off and make the system re-execute the BIOS from ROM as part of a reboot.