From 89d7b30c652c98ea12abc5eb9424464cbfb45953 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Mon, 16 Feb 2026 12:00:12 +0800 Subject: [PATCH] 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 Reviewed by: kib Pull Request: https://github.com/freebsd/freebsd-src/pull/2027 --- sys/amd64/include/cpufunc.h | 14 ++++++-------- sys/i386/include/cpufunc.h | 26 ++++++-------------------- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h index 9a4c82275a9..e52c55dc80f 100644 --- a/sys/amd64/include/cpufunc.h +++ b/sys/amd64/include/cpufunc.h @@ -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) { diff --git a/sys/i386/include/cpufunc.h b/sys/i386/include/cpufunc.h index b200588b073..5ee516656d7 100644 --- a/sys/i386/include/cpufunc.h +++ b/sys/i386/include/cpufunc.h @@ -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) {