i386,amd64: Explicitly set ECX=0 in do_cpuid() to be future-proof

In principle, do_cpuid() should only be used for CPUID leaves without
sub-leaves.  Even accessing sub-leaf zero (ECX=0), one must use
cpuid_count(ax, 0) rather than cpuid(ax).

However, one might assume do_cpuid(ax) is equivalent to
cpuid_count(ax, 0), but the old do_cpuid() did not initialize ECX before
executing the CPUID instruction.  If ECX contained a non-zero value, the
instruction could return unexpected results, potentially leading to
subtle and hard-to-debug issues, especially in ported code.

To be future-proof and to help port code, adjust do_cpuid(ax) to be
cpuid_count(ax, 0) to explicitly set ECX=0.

It's believed that this change does not fix any real bugs in FreeBSD.

See also the DragonFly commit:
https://github.com/DragonFlyBSD/DragonFlyBSD/commit/0087a1d163488a57787a9a6431dd94070b1988d4

Signed-off-by: Aaron LI <aly@aaronly.me>
Reviewed by: kib
Pull Request: https://github.com/freebsd/freebsd-src/pull/2027
This commit is contained in:
Aaron LI
2026-02-16 12:00:12 +08:00
committed by Ed Maste
parent 836ac98993
commit 89d7b30c65
2 changed files with 12 additions and 28 deletions
+6 -8
View File
@@ -99,14 +99,6 @@ disable_intr(void)
__asm __volatile("cli" : : : "memory");
}
static __inline void
do_cpuid(u_int ax, u_int *p)
{
__asm __volatile("cpuid"
: "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
: "0" (ax));
}
static __inline void
cpuid_count(u_int ax, u_int cx, u_int *p)
{
@@ -115,6 +107,12 @@ cpuid_count(u_int ax, u_int cx, u_int *p)
: "0" (ax), "c" (cx));
}
static __inline void
do_cpuid(u_int ax, u_int *p)
{
cpuid_count(ax, 0, p);
}
static __inline void
enable_intr(void)
{
+6 -20
View File
@@ -91,14 +91,6 @@ disable_intr(void)
}
#ifdef _KERNEL
static __inline void
do_cpuid(u_int ax, u_int *p)
{
__asm __volatile("cpuid"
: "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
: "0" (ax));
}
static __inline void
cpuid_count(u_int ax, u_int cx, u_int *p)
{
@@ -107,18 +99,6 @@ cpuid_count(u_int ax, u_int cx, u_int *p)
: "0" (ax), "c" (cx));
}
#else
static __inline void
do_cpuid(u_int ax, u_int *p)
{
__asm __volatile(
"pushl\t%%ebx\n\t"
"cpuid\n\t"
"movl\t%%ebx,%1\n\t"
"popl\t%%ebx"
: "=a" (p[0]), "=DS" (p[1]), "=c" (p[2]), "=d" (p[3])
: "0" (ax));
}
static __inline void
cpuid_count(u_int ax, u_int cx, u_int *p)
{
@@ -132,6 +112,12 @@ cpuid_count(u_int ax, u_int cx, u_int *p)
}
#endif
static __inline void
do_cpuid(u_int ax, u_int *p)
{
cpuid_count(ax, 0, p);
}
static __inline void
enable_intr(void)
{