On Tue, Mar 17, 2026 at 9:12 AM Ewanhaioc <[email protected]> wrote: > > From: Ewan <[email protected]> > > The __get_cpuid() and __get_cpuid_count() functions use > "__leaf & 0x80000000" to determine the CPUID range base, which only > distinguishes between Basic (0x0) and Extended (0x80000000) ranges. > This causes queries to the Centaur/Zhaoxin range (0xC0000000) to be > incorrectly mapped to the Extended range, and always return 0 (failure) > on Centaur/Zhaoxin processors that support CPUID 0xC000xxxx > leaves (e.g. PadLock feature detection via leaf 0xC0000001). > > Replace the bitmask with explicit range checks that correctly identify > all four CPUID ranges: Basic (0x0), Hypervisor (0x40000000), Extended > (0x80000000), and Centaur/Zhaoxin (0xC0000000). > > Additionally, the Hypervisor range (0x40000000) is also handled as an > extra improvement, since the original bitmask incorrectly mapped it to > the Basic range (0x0). > > Also update the __get_cpuid_max() comment to document the newly > supported range base values. > > gcc/ChangeLog: > > * config/i386/cpuid.h (__get_cpuid_max): Update comment to > document 0x40000000 and 0xC0000000 as valid ext values. > (__get_cpuid): Replace "__leaf & 0x80000000" with explicit > range checks for Basic, Hypervisor, Extended, and > Centaur/Zhaoxin CPUID ranges. > (__get_cpuid_count): Likewise.
OK. Thanks, Uros. > > Signed-off-by: Ewanhaioc <[email protected]> > --- > gcc/config/i386/cpuid.h | 29 +++++++++++++++++++++++++---- > 1 file changed, 25 insertions(+), 4 deletions(-) > > diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h > index f493360b1e8..083e4f62498 100644 > --- a/gcc/config/i386/cpuid.h > +++ b/gcc/config/i386/cpuid.h > @@ -264,8 +264,9 @@ > > > /* Return highest supported input value for cpuid instruction. ext can > - be either 0x0 or 0x80000000 to return highest supported value for > - basic or extended cpuid information. Function returns 0 if cpuid > + be either 0x0, 0x40000000, 0x80000000, or 0xC0000000 to return > + highest supported value for basic, hypervisor, extended, or > + Centaur/Zhaoxin cpuid information. Function returns 0 if cpuid > is not supported or whatever cpuid returns in eax register. If sig > pointer is non-null, then first four bytes of the signature > (as found in ebx register) are returned in location pointed by sig. */ > @@ -330,7 +331,17 @@ __get_cpuid (unsigned int __leaf, > unsigned int *__eax, unsigned int *__ebx, > unsigned int *__ecx, unsigned int *__edx) > { > - unsigned int __ext = __leaf & 0x80000000; > + unsigned int __ext; > + > + if (__leaf >= 0xC0000000) > + __ext = 0xC0000000; > + else if (__leaf >= 0x80000000) > + __ext = 0x80000000; > + else if (__leaf >= 0x40000000) > + __ext = 0x40000000; > + else > + __ext = 0x00000000; > + > unsigned int __maxlevel = __get_cpuid_max (__ext, 0); > > if (__maxlevel == 0 || __maxlevel < __leaf) > @@ -347,7 +358,17 @@ __get_cpuid_count (unsigned int __leaf, unsigned int > __subleaf, > unsigned int *__eax, unsigned int *__ebx, > unsigned int *__ecx, unsigned int *__edx) > { > - unsigned int __ext = __leaf & 0x80000000; > + unsigned int __ext; > + > + if (__leaf >= 0xC0000000) > + __ext = 0xC0000000; > + else if (__leaf >= 0x80000000) > + __ext = 0x80000000; > + else if (__leaf >= 0x40000000) > + __ext = 0x40000000; > + else > + __ext = 0x00000000; > + > unsigned int __maxlevel = __get_cpuid_max (__ext, 0); > > if (__builtin_expect (__maxlevel == 0, 0) || __maxlevel < __leaf) > -- > 2.34.1 >
