cpuid() duplicates the old EBX save and restore sequence and leaves the ECX input unspecified. This is unsafe in long mode and makes queries of indexed CPUID leaves depend on the incoming ECX value.
Call cpuid_ext() with subleaf zero to reuse native_cpuid() and provide a deterministic default for indexed leaves. Keep the existing interface so callers do not need to manage individual register outputs. Signed-off-by: Bin Meng <[email protected]> --- arch/x86/include/asm/cpu.h | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index a28bc75def6..9c39ffee062 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -69,26 +69,6 @@ struct cpuid_result { uint32_t edx; }; -/* - * Generic CPUID function - */ -static inline struct cpuid_result cpuid(int op) -{ - struct cpuid_result result; - asm volatile( - "mov %%ebx, %%edi;" - "cpuid;" - "mov %%ebx, %%esi;" - "mov %%edi, %%ebx;" - : "=a" (result.eax), - "=S" (result.ebx), - "=c" (result.ecx), - "=d" (result.edx) - : "0" (op) - : "edi"); - return result; -} - static inline void native_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { @@ -117,6 +97,14 @@ static inline struct cpuid_result cpuid_ext(int op, unsigned int ecx) return result; } +/* + * Generic CPUID function with subleaf zero + */ +static inline struct cpuid_result cpuid(int op) +{ + return cpuid_ext(op, 0); +} + #define native_cpuid_reg(reg) \ static inline unsigned int cpuid_##reg(unsigned int op) \ { \ --- base-commit: 5e3b01c8466dbe45cd6a06299f8f4c7e8c1c2363 branch: cpuid -- 2.53.0
