]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
x86: Update cpuid_eax et al to work on amd64
authorSimon Glass <sjg@chromium.org>
Sat, 15 Mar 2025 14:25:44 +0000 (14:25 +0000)
committerTom Rini <trini@konsulko.com>
Thu, 3 Apr 2025 17:41:55 +0000 (11:41 -0600)
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 <sjg@chromium.org>
arch/x86/include/asm/cpu.h

index 1f1b545ea5071ed404bd7e0659eecc2c475a57da..5d24c17f8a37c23e1395f12d477c368e11c9b97e 100644 (file)
@@ -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)