News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

CPUID on Early P5 Cores

Started by dedndave, June 15, 2014, 02:23:00 PM

Previous topic - Next topic

dedndave

i was doing a little research and came across this article

http://www.os2museum.com/wp/?p=1448

the article is about a "bug" in the installation kernel for a pre-release version of NT
they show some code, then go on to discuss possible workarounds
the workarounds weren't particularly interesting, but the original installation kernel code was

or ebx,0x00200000
push ebx
popfd
cpuid

one can assume that EBX previously held the EFLAGS contents

this is related to one of the many CPUID caveats refered to as "early P5, pre-B0 stepping" behaviour

http://www.sandpile.org/x86/cpuid.htm

QuoteNote that the program may face one of the early Intel P5 processors:
they do neither return a vendor ID string nor the maximum
supported standard level (when level 0000_0000h is queried).
Quotenotes    descriptions
#1    According to [1] and [2] the pre-B0 step Intel P5 processors return EAX=0000_05xxh.
#2    According to [1] and [2] the pre-B0 step Intel P5 processors don't return a vendor ID string.

where [1] and [2] are dead links to old intel asm macro files that may be located elsewhere:

http://fornax.elf.stuba.sk/SUPERMAN/SYSTEMS/DOS/ASM/p5asm.mac
http://fornax.elf.stuba.sk/SUPERMAN/SYSTEMS/DOS/ASM/p5masm.mac

so, first, i want to say that the NT installer code implies that the ID bit (EFLAGS bit 21)
was used to select the CPUID leaf 0 or 1
there is no other reason for explicitly setting that bit
toggle it, yes - set it, no
that would also explain the "signature where highest level should be"
and "no vendor id string" issues
assuming the bit is set, when it should have been reset to get leaf 0 information

also - if the ID bit happens to be cleared, they call CPUID with EAX=0, and get the "expected" results
noone is going to report that as an issue - lol

the other observation i have here is that it is refered to as the "pre-B0 stepping" issue
huh ????   :icon_eek:
the stepping field in the signature dword is only 4 bits
how do you get to "pre-B0" stepping ?
B0 is 8 bits wide, right ?

dedndave

on a related note, i came across some very interesting info from Brendan Trotter on osdev.org...
QuoteExcerpts from an OSDEV.ORG forum post by Brendan Trotter, May 7 2007

A quick list of differences between AMD and Intel (ignoring bugs):

    Cache details - these are reported using entirely different methods. Intel was using arbitrary numerical codes (eax = 0x00000002) which forces software to use a conversion table, but switched to a better method (eax = 0x00000004) that doesn't require a conversion table and returns a little more information (how many logical CPUs share the cache, etc). AMD doesn't support either of these methods but uses it's own version (eax = 0x80000005 for L1 caches and eax = 0x80000006 for L1 caches). I don't know how AMD returns information about L3 caches or information about which caches are shared between different cores (AFAIK this information can't be obtained at all for AMD CPUs).

    Power Management - Intel uses eax = 0x00000006 while AMD use eax = 0x80000007. Both manufacturers do power management in different ways.

    Multi-core - AMD uses eax = 0x80000008 for the number of cores on the chip while Intel uses eax = 0x00000004.

    Feature Flags - in general there's 2 functions for this, eax = 0x00000001 for Intel defined features and eax = 0x80000001 for AMD defined features. Because AMD implements a lot of Intel features and Intel implements some AMD features, you need to use both functions to get a complete list of supported features. Also, Centaur/VIA has some interesting features (e.g. an encryption engine) that are detected using eax = 0xC0000001 (if and only if the CPU vendor string is "CentaurHauls").

    Some features (SYSENTER and SYSCALL) are supported in some modes (e.g. protected mode or long mode) but not others, but there's only one flag to determine if it's supported or not. For example an Intel CPU that supports SYSCALL in long mode will leave the SYSCALL feature flag clear because SYSCALL isn't support in protected mode (unlike AMD). An AMD CPU that supports SYSENTER in protected mode will set the SYSENTER flag even though it doesn't support SYSENTER in long mode (unlike Intel).

The caveats:

On top of this there's CPU bugs where some CPUs say they support features when they don't. For example, Intel Pentium 4 model 3 says it supports CMPXCHG16B when it doesn't, Pentium Pro model 3 stepping 3 says it supports SYSENTER when it doesn't, AMD K5 model 0 says it doesn't support PGE when it does, lots of older CPUs support CMPXCHG8B but don't report it.

Then there's other CPU bugs that can be avoided. For an example there's some Pentium II overdrive chips that support PAT but the upper 4 PAT entries don't work if PSE or PAE is enabled. In this case I just clear the PAE feature flag (in the OS's version of the feature flags) so the OS never uses PAE on these CPUs.

Because of all these problems I parse CPUID information during boot and build (consistent and correct) OS specific information that's used by everything after that. This also means that I can also other methods of detecting information about a CPU and the rest of my software still works the same. Examples of this include building a "brand string" for CPUs that don't support CPUID eax=0x80000002 to CPUID eax=0x80000004; using vendor, family and stepping information to determine cache details; or using I/O ports to get CPU information for older Cyrix CPUs.

Lastly, my OS's code goes even further than this, and builds a set of "errata flags" and a set of "flaw flags". Errata flags are used to tell the OS to use evasive action (i.e. implement some sort of work-around). For example, the CPUID code might set the "has F00F bug" flag, and the OS would handle this by making sure the IDT isn't cached (so the OS won't lock up if malicious code executes the F00F instruction). Because flaw flags are fixed by work-arounds in the OS the user doesn't need to care about them. Errata flags are for things that can cause erratic behavior or reduced stability that have no sane work-around - my CPUID code keeps track of these so they can be reported to system administrators.

@TomTom: Some early Pentium CPUs return the family, model and stepping in EAX for "CPUID eax = 0x00000000" (instead of returning the highest standard function number supported). These CPUs don't return a vendor string, feature flags, or any other information. For these CPUs my code detects them and sets the family, model and stepping to what was reported, then sets the vendor string to "GenuineIntel" and feature flags (FPU, VME, DE, PSE, TSC, MSR, MCE and CX8). Then it uses the family, model and stepping to find a brand string (probably "Pentium (P5)"). Lastly it decides the CPU has the F00F bug (that the OS fixes) and some FPU problems (that the OS can't fix).

Cheers,

Brendan

Gunther

Dave,

very interesting. Do you have such a CPU?

Gunther
You have to know the facts before you can distort them.

dedndave

i don't know, Gunther
out in the garage, i have a few oldies
one is a Pentium II, i think
another is a Pentium III MMX
but, they never had win32 on them - they were set up for win95/win98

FORTRANS

Hi,

   The oldest P5 I have is a Pentium with the math bug.  It is
the one with the dead CMOS memory and clock chip I wrote
about a while back.  I have a mix of older CPU's, but some
would require a floppy boot (if they boot at all...).

Cheers,

Steve N.

dedndave

i have learned that these pre-B0 cores are all pre-production samples
so - not much sweat, there

i have written a little cpuid dump program

i don't need to see the output from everyone on this
i just thought you might like to have it as a handy little tool

for the brand string, leading spaces are not removed and all nulls are converted to periods

0_0EAX: 00000005
0_0EBX: "Genu"
0_0EDX: "ineI"
0_0ECX: "ntel"
0_1EAX: 00000F43
0_1EBX: 01020800
0_1ECX: 0000649D
0_1EDX: BFEBFBFF
8_0EAX: 80000008
8_1EAX: 00000000
8_1EBX: 00000000
8_1ECX: 00000000
8_1EDX: 20100000

"              Intel(R) Pentium(R) 4 CPU 3.00GHz."


EDIT: removed display of leaf 8_0 EBX, ECX, EDX

Zen

DAVE !!!
This is GREAT intelligence !!!
You are ALWAYS on the forefront of weapons-grade CPUID implementation !!!
THANKS !!!
LOL :dazzled:

Gunther

Dave,

from one machine at the University:

0_0EAX: 00000001
0_0EBX: "Auth"
0_0EDX: "enti"
0_0ECX: "cAMD"
0_1EAX: 00060FB2
0_1EBX: 01020800
0_1ECX: 00002001
0_1EDX: 178BFBFF
8_0EAX: 80000018
8_1EAX: 00060FB2
8_1EBX: 00000ED9
8_1ECX: 0000011F
8_1EDX: EBD3FBFF

"AMD Athlon(tm) Dual Core Processor 5000B........"

Press any key to continue ...


Gunther
You have to know the facts before you can distort them.

FORTRANS

Hi Dave,

   Well, as you mentioned early P5 Cores, here are some.  I
should probably let you guess what they are.  But they happen
to be a P-III, P-II, and P-MMX.

0_0EAX: 00000002
0_0EBX: "Genu"
0_0EDX: "ineI"
0_0ECX: "ntel"
0_1EAX: 00000683
0_1EBX: 00000002
0_1ECX: 00000000
0_1EDX: 0383F9FF

Press any key to continue ...

0_0EAX: 00000002
0_0EBX: "Genu"
0_0EDX: "ineI"
0_0ECX: "ntel"
0_1EAX: 00000652
0_1EBX: 00000000
0_1ECX: 00000000
0_1EDX: 0183F9FF

Press any key to continue ...

0_0EAX: 00000001
0_0EBX: "Genu"
0_0EDX: "ineI"
0_0ECX: "ntel"
0_1EAX: 00000543
0_1EBX: 00000000
0_1ECX: 00000000
0_1EDX: 008001BF

Press any key to continue ...


HTH,

Steve

dedndave

that's cool, Steve
i see you don't have any of the "pre-B0" CPU's   :P

Gunther

Dave,

result from my desktop PC at home:

0_0EAX: 0000000D
0_0EBX: "Genu"
0_0EDX: "ineI"
0_0ECX: "ntel"
0_1EAX: 000306A9
0_1EBX: 04100800
0_1ECX: 7FBAE3FF
0_1EDX: BFEBFBFF
8_0EAX: 80000008
8_1EAX: 00000000
8_1EBX: 00000000
8_1ECX: 00000001
8_1EDX: 28100000

"        Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz."

Press any key to continue ...


Gunther
You have to know the facts before you can distort them.

dedndave

that's a nice processor, Gunther   :t

RuiLoureiro

Quote
0_0EAX: 00000005
0_0EBX: "Genu"
0_0EDX: "ineI"
0_0ECX: "ntel"
0_1EAX: 00000F43
0_1EBX: 01020800
0_1ECX: 0000649D
0_1EDX: BFEBFBFF
8_0EAX: 80000008
8_1EAX: 00000000
8_1EBX: 00000000
8_1ECX: 00000000
8_1EDX: 20100000
"              Intel(R) Pentium(R) 4 CPU 3.40GHz.",   Dave  :t

Press any key to continue ...

Gunther

Dave,

Quote from: dedndave on June 21, 2014, 03:55:23 AM
that's a nice processor, Gunther   :t

Yes, of course. After 10 years AMD I'm back with an Intel CPU.

Gunther
You have to know the facts before you can distort them.

dedndave

except for APIC ID and clock frequency, yours is the same as mine, Rui   ;)