1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
crate::ix!();

/**
  | Read 64 bits of entropy using rdseed.
  | 
  | Must only be called when RdSeed is supported.
  |
  */
#[cfg(have_getcpuid)]
pub fn get_rd_seed() -> u64 {
    
    // RdSeed may fail when the HW RNG is
    // overloaded. Loop indefinitely until enough
    // entropy is gathered, but pause after every
    // failure.
    #[cfg(i386)]
    {
        let ok:  u8 = 0;
        let r1: u32 = 0;
        let r2: u32 = 0;

        loop {

            // rdseed %eax
            asm!{".byte 0x0f, 0xc7, 0xf8; setc %1" 
                : "=a"(r1), "=q"(ok) :: "cc" : "volatile"}; 

            if ok != 0 {
                break;
            }

            asm!{"pause" : "volatile"};
        }

        loop {

            // rdseed %eax
            asm!{".byte 0x0f, 0xc7, 0xf8; setc %1" 
                : "=a"(r2), "=q"(ok) :: "cc" : "volatile" }; 

            if ok != 0 {
                break;
            }

            asm!{"pause" : "volatile"};
        }

        return ((r2 as u64) << 32) | r1;
    }

    #[cfg(x86_64_or_amd64)]
    {
        let ok:  u8 = 0;
        let r1: u64 = 0;

        loop {

            // rdseed %rax
            asm!{".byte 0x48, 0x0f, 0xc7, 0xf8; setc %1" 
                : "=a"(r1), "=q"(ok) :: "cc" : "volatile"}; 

            if ok != 0 {
                break;
            }

            asm!{"pause" : "volatile"};
        }

        return r1;
    }

    panic!{"RdSeed is only supported on x86 and x86_64"}
}