[systemd-devel] rdrand generated with march=winchip-c6 in systemd-241
tedheadster
tedheadster at gmail.com
Tue May 7 14:45:27 UTC 2019
On Tue, May 7, 2019 at 10:27 AM Segher Boessenkool
<segher at kernel.crashing.org> 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
More information about the systemd-devel
mailing list