20#include "pedigree/kernel/processor/types.h"
21#include "pedigree/kernel/utilities/lib.h"
23static uint64_t g_Seed = 1;
26static volatile int g_FeaturesChecked = 0;
27static int g_HasRdseed = 0;
28static int g_HasRdrand = 0;
30static void random_cpuid(uint32_t leaf, uint32_t subleaf, uint32_t* eax, uint32_t* ebx,
31 uint32_t* ecx, uint32_t* edx) {
36 __asm__
volatile(
"cpuid" :
"+a"(a),
"=b"(b),
"+c"(c),
"=d"(d) : :
"memory");
43static void random_check_features(
void) {
44 if (g_FeaturesChecked) {
52 random_cpuid(0, 0, &eax, &ebx, &ecx, &edx);
53 const uint32_t maximumLeaf = eax;
55 if (maximumLeaf >= 1) {
56 random_cpuid(1, 0, &eax, &ebx, &ecx, &edx);
57 g_HasRdrand = (ecx & (1U << 30U)) != 0;
59 if (maximumLeaf >= 7) {
60 random_cpuid(7, 0, &eax, &ebx, &ecx, &edx);
61 g_HasRdseed = (ebx & (1U << 18U)) != 0;
65 g_FeaturesChecked = 1;
68static int random_hardware_word(uint64_t* value) {
69 random_check_features();
72 for (
size_t attempt = 0; attempt < 10; ++attempt) {
74 uint64_t candidate = 0;
75 __asm__
volatile(
"rdrand %0; setc %1" :
"=r"(candidate),
"=qm"(ok) : :
"cc");
80 __asm__
volatile(
"pause");
85 for (
size_t attempt = 0; attempt < 64; ++attempt) {
87 uint64_t candidate = 0;
88 __asm__
volatile(
"rdseed %0; setc %1" :
"=r"(candidate),
"=qm"(ok) : :
"cc");
93 __asm__
volatile(
"pause");
101void random_seed(uint64_t seed) {
105uint64_t random_next() {
107 g_Seed = (g_Seed * 6364136223846793005ULL) + 1442695040888963407ULL;
111size_t hardware_random_bytes(
void* buffer,
size_t length) {
113 uint8_t* output = (uint8_t*)buffer;
115 while (produced < length) {
117 if (!random_hardware_word(&value)) {
121 for (
size_t byte = 0;
byte <
sizeof(value) && produced < length; ++byte) {
122 output[produced++] = (uint8_t)value;