On Tue, May 7, 2019 at 10:27 AM Segher Boessenkool <segher@xxxxxxxxxxxxxxxxxxx> wrote: > But it should not execute it, it is guarded by some cpuid things. > > If the assembler does not like the insn, first do (in the same asm) an > assembler pseudo-instruction to select a CPU that does have that insn, > then the rdrand, and then the original CPU again. Or write the bytes > of the instruction encoding directly. Segher, you are correct that the code should avoid executing the rdrand instruction by doing some cpuid queries. The problem is that does not work: systemd _does_ execute the rdrand instruction and the system crashes. So there is something wrong with the cpuid logic or results. This system _does_ support cpuid. Here is the raw data from it: # cpuid -r CPU 0: 0x00000000 0x00: eax=0x00000001 ebx=0x746e6543 ecx=0x736c7561 edx=0x48727561 0x00000001 0x00: eax=0x00000585 ebx=0x00000000 ecx=0x00000000 edx=0x008001b5 <--- look at %ecx 0x80000000 0x00: eax=0x80000005 ebx=0x00000001 ecx=0x00000000 edx=0x00000050 0x80000001 0x00: eax=0x00000585 ebx=0x00000001 ecx=0x00000000 edx=0x808001b5 0x80000002 0x00: eax=0x20544449 ebx=0x436e6957 ecx=0x20706968 edx=0x44332d32 0x80000003 0x00: eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 0x80000004 0x00: eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 0x80000005 0x00: eax=0x80000005 ebx=0x08800880 ecx=0x20040120 edx=0x20020120 0x80860000 0x00: eax=0x80860000 ebx=0x08800880 ecx=0x00000000 edx=0x00000050 0xc0000000 0x00: eax=0xc0000005 ebx=0x08800880 ecx=0x00000000 edx=0x00000050 0xc0000001 0x00: eax=0x00000585 ebx=0x08800880 ecx=0x00000000 edx=0x808001b5 0xc0000002 0x00: eax=0x20544449 ebx=0x436e6957 ecx=0x20706968 edx=0x44332d32 0xc0000003 0x00: eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 0xc0000004 0x00: eax=0x00000000 ebx=0x00000000 ecx=0x00000000 edx=0x00000000 0xc0000005 0x00: eax=0xc0000005 ebx=0x08800880 ecx=0x20040120 edx=0x20020120 So cpuid query 0x1 returns 0x0 in the %ecx register. I believe this means that rdrand is not supported (bit 30 is not set). Yet the code executes it anyhow. Here is the full disassembly with a few comments: (gdb) disassemble Dump of assembler code for function rdrand: 0xb7e21440 <+0>: push %esi 0xb7e21441 <+1>: push %ebx 0xb7e21442 <+2>: call 0xb7e0af5d <__x86.get_pc_thunk.si> 0xb7e21447 <+7>: add $0x1acb39,%esi 0xb7e2144d <+13>: mov 0x2870(%esi),%ecx 0xb7e21453 <+19>: test %ecx,%ecx 0xb7e21455 <+21>: js 0xb7e21480 <rdrand+64> 0xb7e21457 <+23>: test %ecx,%ecx 0xb7e21459 <+25>: je 0xb7e214e0 <rdrand+160> 0xb7e2145f <+31>: rdrand %ecx <---- illegal instruction was attempted here 0xb7e21462 <+34>: setb %al 0xb7e21465 <+37>: mov 0xc(%esp),%edx 0xb7e21469 <+41>: mov %ecx,(%edx) 0xb7e2146b <+43>: cmp $0x1,%al 0xb7e2146d <+45>: sbb %eax,%eax 0xb7e2146f <+47>: and $0xfffffff5,%eax 0xb7e21472 <+50>: pop %ebx 0xb7e21473 <+51>: pop %esi 0xb7e21474 <+52>: ret 0xb7e21475 <+53>: lea 0x0(%esi,%eiz,1),%esi 0xb7e21479 <+57>: lea 0x0(%edi,%eiz,1),%edi 0xb7e21480 <+64>: pushf 0xb7e21481 <+65>: pushf 0xb7e21482 <+66>: pop %eax 0xb7e21483 <+67>: mov %eax,%edx 0xb7e21485 <+69>: xor $0x200000,%eax 0xb7e2148a <+74>: push %eax 0xb7e2148b <+75>: popf 0xb7e2148c <+76>: pushf 0xb7e2148d <+77>: pop %eax 0xb7e2148e <+78>: popf 0xb7e2148f <+79>: xor %edx,%eax 0xb7e21491 <+81>: test $0x200000,%eax <--- checks if cpuid is supported 0xb7e21496 <+86>: je 0xb7e214c0 <rdrand+128> 0xb7e21498 <+88>: xor %eax,%eax 0xb7e2149a <+90>: cpuid 0xb7e2149c <+92>: test %eax,%eax 0xb7e2149e <+94>: je 0xb7e214c0 <rdrand+128> 0xb7e214a0 <+96>: mov $0x1,%eax <--- checks if cpuid query 0x1 is supported 0xb7e214a5 <+101>: cpuid 0xb7e214a7 <+103>: shr $0x1e,%ecx <---- shifts right 30 bits to rdrand position 0xb7e214aa <+106>: and $0x1,%ecx <--- checks if rdrand is supported 0xb7e214ad <+109>: mov %ecx,0x2870(%esi) 0xb7e214b3 <+115>: jmp 0xb7e21457 <rdrand+23> 0xb7e214b5 <+117>: lea 0x0(%esi,%eiz,1),%esi 0xb7e214b9 <+121>: lea 0x0(%edi,%eiz,1),%edi 0xb7e214c0 <+128>: movl $0x0,0x2870(%esi) 0xb7e214ca <+138>: mov $0xffffffa1,%eax 0xb7e214cf <+143>: jmp 0xb7e21472 <rdrand+50> 0xb7e214d1 <+145>: jmp 0xb7e214e0 <rdrand+160> 0xb7e214d3 <+147>: nop 0xb7e214d4 <+148>: nop 0xb7e214d5 <+149>: nop 0xb7e214d6 <+150>: nop 0xb7e214d7 <+151>: nop 0xb7e214d8 <+152>: nop 0xb7e214d9 <+153>: nop 0xb7e214da <+154>: nop 0xb7e214db <+155>: nop 0xb7e214dc <+156>: nop 0xb7e214dd <+157>: nop 0xb7e214de <+158>: nop 0xb7e214df <+159>: nop 0xb7e214e0 <+160>: mov $0xffffffa1,%eax 0xb7e214e5 <+165>: jmp 0xb7e21472 <rdrand+5 - Matthew Whitehead