The existing functions work but the register clobbers are wrong, so strange bugs results.
The original functions were taken from a very old version of Linux. Update them from Linux 6.13 Signed-off-by: Simon Glass <s...@chromium.org> --- (no changes since v3) Changes in v3: - Add new patch to update cpuid_eax et al to work on amd64 arch/x86/include/asm/cpu.h | 75 +++++++++++++------------------------- 1 file changed, 25 insertions(+), 50 deletions(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 1f1b545ea50..5d24c17f8a3 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -109,61 +109,36 @@ static inline struct cpuid_result cpuid_ext(int op, unsigned ecx) return result; } -/* - * CPUID functions returning a single datum - */ -static inline unsigned int cpuid_eax(unsigned int op) +static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) { - unsigned int eax; - - __asm__("mov %%ebx, %%edi;" - "cpuid;" - "mov %%edi, %%ebx;" - : "=a" (eax) - : "0" (op) - : "ecx", "edx", "edi"); - return eax; + /* ecx is often an input as well as an output. */ + asm volatile("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (*eax), "2" (*ecx) + : "memory"); } -static inline unsigned int cpuid_ebx(unsigned int op) -{ - unsigned int eax, ebx; - - __asm__("mov %%ebx, %%edi;" - "cpuid;" - "mov %%ebx, %%esi;" - "mov %%edi, %%ebx;" - : "=a" (eax), "=S" (ebx) - : "0" (op) - : "ecx", "edx", "edi"); - return ebx; +#define native_cpuid_reg(reg) \ +static inline unsigned int cpuid_##reg(unsigned int op) \ +{ \ + unsigned int eax = op, ebx, ecx = 0, edx; \ + \ + native_cpuid(&eax, &ebx, &ecx, &edx); \ + \ + return reg; \ } -static inline unsigned int cpuid_ecx(unsigned int op) -{ - unsigned int eax, ecx; - - __asm__("mov %%ebx, %%edi;" - "cpuid;" - "mov %%edi, %%ebx;" - : "=a" (eax), "=c" (ecx) - : "0" (op) - : "edx", "edi"); - return ecx; -} - -static inline unsigned int cpuid_edx(unsigned int op) -{ - unsigned int eax, edx; - - __asm__("mov %%ebx, %%edi;" - "cpuid;" - "mov %%edi, %%ebx;" - : "=a" (eax), "=d" (edx) - : "0" (op) - : "ecx", "edi"); - return edx; -} +/* + * Native CPUID functions returning a single datum. + */ +native_cpuid_reg(eax) +native_cpuid_reg(ebx) +native_cpuid_reg(ecx) +native_cpuid_reg(edx) #if CONFIG_IS_ENABLED(X86_64) static inline int flag_is_changeable_p(u32 flag) -- 2.43.0