mb/google/skyrim: Enable Chrome EC
[coreboot.git] / src / arch / x86 / rdrand.c
blob5374933b5e0c4c8f051982139d449473bf99f7c6
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <random.h>
5 /*
6 * Intel recommends that applications attempt 10 retries in a tight loop
7 * in the unlikely event that the RDRAND instruction does not successfully
8 * return a random number. The odds of ten failures in a row would in fact
9 * be an indication of a larger CPU issue.
11 #define RDRAND_RETRY_LOOPS 10
14 * Generate a 32-bit random number through RDRAND instruction.
15 * Carry flag is set on RDRAND success and 0 on failure.
17 static inline uint8_t rdrand_32(uint32_t *rand)
19 uint8_t carry;
21 __asm__ __volatile__(
22 ".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
23 : "=a" (*rand), "=qm" (carry));
24 return carry;
27 #if ENV_X86_64
29 * Generate a 64-bit random number through RDRAND instruction.
30 * Carry flag is set on RDRAND success and 0 on failure.
32 static inline uint8_t rdrand_64(uint64_t *rand)
34 uint8_t carry;
36 __asm__ __volatile__(
37 ".byte 0x48; .byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
38 : "=a" (*rand), "=qm" (carry));
39 return carry;
41 #endif
43 int get_random_number_32(uint32_t *rand)
45 int i;
47 /* Perform a loop call until RDRAND succeeds or returns failure. */
48 for (i = 0; i < RDRAND_RETRY_LOOPS; i++) {
49 if (rdrand_32(rand))
50 return 0;
52 return -1;
55 int get_random_number_64(uint64_t *rand)
57 int i;
58 uint32_t rand_high, rand_low;
60 /* Perform a loop call until RDRAND succeeds or returns failure. */
61 for (i = 0; i < RDRAND_RETRY_LOOPS; i++) {
62 #if ENV_X86_64
63 if (rdrand_64(rand))
64 return 0;
65 #endif
66 if (rdrand_32(&rand_high) && rdrand_32(&rand_low)) {
67 *rand = ((uint64_t)rand_high << 32) |
68 (uint64_t)rand_low;
69 return 0;
72 return -1;