MAINTAINERS: Add Yuchi and Vasiliy for Intel Atom Snow Ridge SoC
[coreboot.git] / src / arch / x86 / rdrand.c
blob31958dba7ffa5c38b01d0afbbce90e501ad7282d
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <random.h>
4 #include <types.h>
6 /*
7 * Intel recommends that applications attempt 10 retries in a tight loop
8 * in the unlikely event that the RDRAND instruction does not successfully
9 * return a random number. The odds of ten failures in a row would in fact
10 * be an indication of a larger CPU issue.
12 #define RDRAND_RETRY_LOOPS 10
15 * Generate a 32-bit random number through RDRAND instruction.
16 * Carry flag is set on RDRAND success and 0 on failure.
18 static inline uint8_t rdrand_32(uint32_t *rand)
20 uint8_t carry;
22 __asm__ __volatile__(
23 ".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
24 : "=a" (*rand), "=qm" (carry));
25 return carry;
28 #if ENV_X86_64
30 * Generate a 64-bit random number through RDRAND instruction.
31 * Carry flag is set on RDRAND success and 0 on failure.
33 static inline uint8_t rdrand_64(uint64_t *rand)
35 uint8_t carry;
37 __asm__ __volatile__(
38 ".byte 0x48; .byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1"
39 : "=a" (*rand), "=qm" (carry));
40 return carry;
42 #endif
44 enum cb_err get_random_number_32(uint32_t *rand)
46 int i;
48 /* Perform a loop call until RDRAND succeeds or returns failure. */
49 for (i = 0; i < RDRAND_RETRY_LOOPS; i++) {
50 if (rdrand_32(rand))
51 return CB_SUCCESS;
53 return CB_ERR;
56 enum cb_err get_random_number_64(uint64_t *rand)
58 int i;
59 uint32_t rand_high, rand_low;
61 /* Perform a loop call until RDRAND succeeds or returns failure. */
62 for (i = 0; i < RDRAND_RETRY_LOOPS; i++) {
63 #if ENV_X86_64
64 if (rdrand_64(rand))
65 return CB_SUCCESS;
66 #endif
67 if (rdrand_32(&rand_high) && rdrand_32(&rand_low)) {
68 *rand = ((uint64_t)rand_high << 32) |
69 (uint64_t)rand_low;
70 return CB_SUCCESS;
73 return CB_ERR;