cpuid_ext() saves and restores EBX with 32-bit moves, which clear the
upper half of RBX in long mode. The assembly does not declare RBX as
an output, so the compiler cannot account for this change.

Initialize the leaf and subleaf in cpuid_result and use native_cpuid(),
which declares all four output registers and lets the compiler preserve
RBX correctly. Keep the structure-returning interface for callers.

Signed-off-by: Bin Meng <[email protected]>
---

 arch/x86/include/asm/cpu.h | 35 +++++++++++++++--------------------
 1 file changed, 15 insertions(+), 20 deletions(-)

diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 1217cebb9b9..a28bc75def6 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -89,26 +89,6 @@ static inline struct cpuid_result cpuid(int op)
        return result;
 }
 
-/*
- * Generic Extended CPUID function
- */
-static inline struct cpuid_result cpuid_ext(int op, unsigned ecx)
-{
-       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), "2" (ecx)
-               : "edi");
-       return result;
-}
-
 static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
                                unsigned int *ecx, unsigned int *edx)
 {
@@ -122,6 +102,21 @@ static inline void native_cpuid(unsigned int *eax, 
unsigned int *ebx,
            : "memory");
 }
 
+/*
+ * Generic Extended CPUID function
+ */
+static inline struct cpuid_result cpuid_ext(int op, unsigned int ecx)
+{
+       struct cpuid_result result = {
+               .eax = op,
+               .ecx = ecx,
+       };
+
+       native_cpuid(&result.eax, &result.ebx, &result.ecx, &result.edx);
+
+       return result;
+}
+
 #define native_cpuid_reg(reg)                                  \
 static inline unsigned int cpuid_##reg(unsigned int op)        \
 {                                                              \
---
base-commit: 5e3b01c8466dbe45cd6a06299f8f4c7e8c1c2363
branch: cpuid

-- 
2.53.0

Reply via email to