On Sat, May 18, 2019 at 6:57 PM Segher Boessenkool <segher@xxxxxxxxxxxxxxxxxxx> wrote: > Something like > > *__ebx = *__ecx = *__edx = 0; > asm volatile("" : "+r"(*__eax), "+r"(*__ebx), "+r"(*__ecx), "+r"(*__edx)); > __cpuid (__leaf, *__eax, *__ebx, *__ecx, *__edx); > > should do the trick. Segher, that got closer, but not quite there. I made a change to your suggesting and got what I think I want: 0xb7e21491 <+81>: test $0x200000,%eax 0xb7e21496 <+86>: je 0xb7e214c0 <rdrand+128> 0xb7e21498 <+88>: xor %edi,%edi <--- zeroes %edi for use below 0xb7e2149a <+90>: mov %edi,%eax 0xb7e2149c <+92>: cpuid 0xb7e2149e <+94>: test %eax,%eax 0xb7e214a0 <+96>: je 0xb7e214c0 <rdrand+128> 0xb7e214a2 <+98>: mov %edi,%ebx <--- zeroes %ebx 0xb7e214a4 <+100>: mov %edi,%ecx <--- zeroes %ecx 0xb7e214a6 <+102>: mov %edi,%edx <--- zeroes %edx 0xb7e214a8 <+104>: mov $0x1,%eax 0xb7e214ad <+109>: cpuid 0xb7e214af <+111>: shr $0x1e,%ecx 0xb7e214b2 <+114>: and $0x1,%ecx 0xb7e214b5 <+117>: mov %ecx,0x35a0(%esi) 0xb7e214bb <+123>: jmp 0xb7e21458 <rdrand+24> Here is the patch: --- cpuid.h.orig 2019-05-14 05:52:11.000000000 -0400 +++ cpuid.h 2019-05-18 21:25:27.000000000 -0400 @@ -251,6 +251,14 @@ if (__maxlevel == 0 || __maxlevel < __leaf) return 0; + /* At least one confirmed cpu (Winchip 2) does not set %ecx correctly for + cpuid() and leaves garbage in it upon return ('auls' from 'CentaurHauls' + in %ebx:%edx:%ecx vendor identification string). Forcibly zero the + registers before calling cpuid() as a precaution. */ + + *__ebx = *__ecx = *__edx = 0; + asm volatile("" : "+b" (*__ebx), "+c" (*__ecx), "+d" (*__edx)); + __cpuid (__leaf, *__eax, *__ebx, *__ecx, *__edx); return 1; } I tested this with systemd on real hardware and it worked nicely. - Matthew