Re: [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>
From: H. Peter Anvin
Date: Tue Mar 18 2025 - 15:10:49 EST
On 3/18/25 11:48, H. Peter Anvin wrote:
One more thing is that we ought to be able to make cpuid a const
function, allowing the compiler to elide multiple calls. (Slight warning
for feature-enabling MSRs changing CPUID), but that would require
changing the API to returning a structure, since a pure or const
structure can't return values by reference.
So I experimented (test included) and found that gcc 14.2 does not seem
to merge the cpuid calls in this code, whereas clang 19.1 does.
-hpa
#include <inttypes.h>
#include <stdio.h>
typedef uint32_t u32;
struct cpuid {
u32 ebx;
u32 edx;
u32 ecx;
u32 eax;
};
static inline __attribute__((const)) struct cpuid
cpuid(u32 leaf, u32 subleaf)
{
struct cpuid rv;
asm("cpuid"
: "=a" (rv.eax), "=c" (rv.ecx), "=d" (rv.edx), "=b" (rv.ebx)
: "a" (leaf), "c" (subleaf));
return rv;
}
static inline __attribute__((const)) u32
cpuid_eax(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.eax;
}
static inline __attribute__((const)) u32
cpuid_ecx(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.ecx;
}
static inline __attribute__((const)) u32
cpuid_edx(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.edx;
}
static inline __attribute__((const)) u32
cpuid_ebx(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.ebx;
}
u32 eax(u32 leaf, u32 subleaf)
{
return cpuid_eax(leaf, subleaf);
}
struct cpuid _cpuid(u32 leaf, u32 subleaf)
{
return cpuid(leaf, subleaf);
}
int test_cpuid(void)
{
int found = 0;
found += !!(cpuid_edx(1, 0) & (1 << 26)); /* SSE2 */
found += !!(cpuid_ecx(1, 0) & (1 << 0)); /* SSE3 */
found += !!(cpuid(1, 0).ecx & (1 << 9)); /* SSSE3 */
return found;
}