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:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user