diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 2927131758..72b9137a2e 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -64,6 +64,7 @@ set(KERNEL_SOURCES kernel/PCI.cpp kernel/PIC.cpp kernel/Process.cpp + kernel/Random.cpp kernel/Scheduler.cpp kernel/Semaphore.cpp kernel/SpinLock.cpp diff --git a/kernel/include/kernel/Random.h b/kernel/include/kernel/Random.h new file mode 100644 index 0000000000..2297721c28 --- /dev/null +++ b/kernel/include/kernel/Random.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +namespace Kernel +{ + + class Random + { + public: + static void initialize(); + static uint32_t get_u32(); + static uint64_t get_u64(); + }; + +} diff --git a/kernel/kernel/Random.cpp b/kernel/kernel/Random.cpp new file mode 100644 index 0000000000..85ba355acd --- /dev/null +++ b/kernel/kernel/Random.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +namespace Kernel +{ + + + // Constants and algorithm from https://en.wikipedia.org/wiki/Permuted_congruential_generator + + static uint64_t s_rand_seed = 0x4d595df4d0f33173; + static constexpr uint64_t s_rand_multiplier = 6364136223846793005; + static constexpr uint64_t s_rand_increment = 1442695040888963407; + + void Random::initialize() + { + uint32_t ecx, edx; + CPUID::get_features(ecx, edx); + + if (ecx & CPUID::ECX_RDRND) + asm volatile("rdrand %0" : "=a"(s_rand_seed)); + else + dprintln("No RDRAND available"); + } + + uint32_t Random::get_u32() + { + auto rotr32 = [](uint32_t x, unsigned r) { return x >> r | x << (-r & 31); }; + + uint64_t x = s_rand_seed; + unsigned count = (unsigned)(x >> 59); + + s_rand_seed = x * s_rand_multiplier + s_rand_increment; + x ^= x >> 18; + + return rotr32(x >> 27, count) % UINT32_MAX; + } + + uint64_t Random::get_u64() + { + return ((uint64_t)get_u32() << 32) | get_u32(); + } + +} diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index e350a60637..dda33d3e6f 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -153,6 +154,9 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info) dprintln("Virtual TTY initialized"); } + Random::initialize(); + dprintln("RNG initialized"); + MUST(Scheduler::initialize()); dprintln("Scheduler initialized");