diff options
| author | Aaron LI <aly@aaronly.me> | 2026-02-16 04:00:12 +0000 |
|---|---|---|
| committer | Ed Maste <emaste@FreeBSD.org> | 2026-02-20 15:26:20 +0000 |
| commit | 89d7b30c652c98ea12abc5eb9424464cbfb45953 (patch) | |
| tree | c54ba0748b0c129a9221cfbd26049747ac1740f0 | |
| parent | 836ac989933bcd5b662979bfdec429a201c123a6 (diff) | |
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
| -rw-r--r-- | sys/amd64/include/cpufunc.h | 10 | ||||
| -rw-r--r-- | sys/i386/include/cpufunc.h | 24 |
2 files changed, 9 insertions, 25 deletions
diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h index 9a4c82275a99..e52c55dc80f0 100644 --- a/sys/amd64/include/cpufunc.h +++ b/sys/amd64/include/cpufunc.h @@ -100,19 +100,17 @@ disable_intr(void) } static __inline void -do_cpuid(u_int ax, u_int *p) +cpuid_count(u_int ax, u_int cx, u_int *p) { __asm __volatile("cpuid" : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) - : "0" (ax)); + : "0" (ax), "c" (cx)); } static __inline void -cpuid_count(u_int ax, u_int cx, u_int *p) +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), "c" (cx)); + cpuid_count(ax, 0, p); } static __inline void diff --git a/sys/i386/include/cpufunc.h b/sys/i386/include/cpufunc.h index b200588b0739..5ee516656d72 100644 --- a/sys/i386/include/cpufunc.h +++ b/sys/i386/include/cpufunc.h @@ -92,14 +92,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) { __asm __volatile("cpuid" @@ -108,7 +100,7 @@ cpuid_count(u_int ax, u_int cx, u_int *p) } #else static __inline void -do_cpuid(u_int ax, u_int *p) +cpuid_count(u_int ax, u_int cx, u_int *p) { __asm __volatile( "pushl\t%%ebx\n\t" @@ -116,21 +108,15 @@ do_cpuid(u_int ax, u_int *p) "movl\t%%ebx,%1\n\t" "popl\t%%ebx" : "=a" (p[0]), "=DS" (p[1]), "=c" (p[2]), "=d" (p[3]) - : "0" (ax)); + : "0" (ax), "c" (cx)); } +#endif static __inline void -cpuid_count(u_int ax, u_int cx, u_int *p) +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), "c" (cx)); + cpuid_count(ax, 0, p); } -#endif static __inline void enable_intr(void) |
