On Sun, May 19, 2019 at 12:10 PM tedheadster <tedheads...@gmail.com> wrote:
>
> I have confirmed that the IDT Winchip 2 does not expressly set %ecx
> after a call to cpuid() with %eax = 1, and this causes incorrect
> reporting of cpu capabilities. The %ecx register should return 0x0
> (and likely %ebx should too) on this hardware. This patch proposes a
> fix.
>
> The symptoms of this arose on a Winchip 2 system when systemd called
> cpuid() with %eax = 1 and it incorrectly reported rdrand() support
> (bit 30 set in %ecx). A call to the supposedly supported rdrand()
> function triggered an illegal instruction exception, causing the
> system to panic early in booting.
>
> The IDT Winchip documentation is silent on what happens to %ecx and
> %ebx after such a call (see below). It appears to leave whatever is in
> %ecx untouched instead of zeroing it. This patch defensively zeroes
> out %ebx:%ecx:%edx before such a call in cpuid.h.
>
> I should be able to test the earlier Winchip C6 model in the future. I
> wlll also check older AMD, Cyrix, and VIA processors.
>
> Thanks to Mike Gilbert for suggesting the solution. Thank you also to
> Segher Boessenkool for helping get the inline assembly syntax correct.

Sorry for the lack of feedback; your mails were getting filed into my
systemd-devel label and I only review that every few days.

I think it would be simpler/better to clear the registers within the
__cpuid macro itself. Something like this I think:

diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index 8ddd425c8b7..ae05bfc6114 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -188,7 +188,10 @@
 #define signature_VORTEX_edx   0x36387865

 #define __cpuid(level, a, b, c, d)                     \
-  __asm__ ("cpuid\n\t"                                 \
+  __asm__ ("xorl\t%1, %1\n\t"                           \
+          "xorl\t%2, %2\n\t"                           \
+          "xorl\t%3, %3\n\t"                           \
+          "cpuid\n\t"                                  \
           : "=a" (a), "=b" (b), "=c" (c), "=d" (d)     \
           : "0" (level))

Reply via email to