From 8e4be9aef92058f75f91b8ad60dfd0f72fce07e7 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 7 Apr 2021 12:42:35 -0700 Subject: [PATCH] kern: simplify global rng initialization --- .../nintendo/nx/kern_k_system_control.cpp | 38 ++++++++++++------- libraries/libmesosphere/source/kern_main.cpp | 6 +++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp index b689d19ea..c10312bde 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp @@ -42,8 +42,8 @@ namespace ams::kern::board::nintendo::nx { /* Nintendo uses std::mt19937_t for randomness. */ /* To save space (and because mt19337_t isn't secure anyway), */ /* We will use TinyMT. */ - bool g_initialized_random_generator; - util::TinyMT g_random_generator; + constinit bool g_initialized_random_generator; + constinit util::TinyMT g_random_generator; constinit KSpinLock g_random_lock; ALWAYS_INLINE size_t GetRealMemorySizeForInit() { @@ -90,13 +90,10 @@ namespace ams::kern::board::nintendo::nx { return value; } - void EnsureRandomGeneratorInitialized() { - if (AMS_UNLIKELY(!g_initialized_random_generator)) { - u64 seed; - smc::GenerateRandomBytes(&seed, sizeof(seed)); - g_random_generator.Initialize(reinterpret_cast(&seed), sizeof(seed) / sizeof(u32)); - g_initialized_random_generator = true; - } + ALWAYS_INLINE u64 GenerateRandomU64FromSmc() { + u64 value; + smc::GenerateRandomBytes(std::addressof(value), sizeof(value)); + return value; } ALWAYS_INLINE u64 GenerateRandomU64FromGenerator() { @@ -439,6 +436,14 @@ namespace ams::kern::board::nintendo::nx { /* System Initialization. */ void KSystemControl::InitializePhase1() { + /* Initialize our random generator. */ + { + u64 seed; + smc::GenerateRandomBytes(std::addressof(seed), sizeof(seed)); + g_random_generator.Initialize(reinterpret_cast(std::addressof(seed)), sizeof(seed) / sizeof(u32)); + g_initialized_random_generator = true; + } + /* Set IsDebugMode. */ { KTargetSystem::SetIsDebugMode(GetConfigBool(smc::ConfigItem::IsDebugMode)); @@ -544,18 +549,23 @@ namespace ams::kern::board::nintendo::nx { KScopedInterruptDisable intr_disable; KScopedSpinLock lk(g_random_lock); - EnsureRandomGeneratorInitialized(); - return GenerateUniformRange(min, max, GenerateRandomU64FromGenerator); + if (AMS_LIKELY(g_initialized_random_generator)) { + return GenerateUniformRange(min, max, GenerateRandomU64FromGenerator); + } else { + return GenerateUniformRange(min, max, GenerateRandomU64FromSmc); + } } u64 KSystemControl::GenerateRandomU64() { KScopedInterruptDisable intr_disable; KScopedSpinLock lk(g_random_lock); - EnsureRandomGeneratorInitialized(); - - return GenerateRandomU64FromGenerator(); + if (AMS_LIKELY(g_initialized_random_generator)) { + return GenerateRandomU64FromGenerator(); + } else { + return GenerateRandomU64FromSmc(); + } } void KSystemControl::SleepSystem() { diff --git a/libraries/libmesosphere/source/kern_main.cpp b/libraries/libmesosphere/source/kern_main.cpp index 5ee230a41..dc351c708 100644 --- a/libraries/libmesosphere/source/kern_main.cpp +++ b/libraries/libmesosphere/source/kern_main.cpp @@ -49,6 +49,9 @@ namespace ams::kern { /* Initialize the carveout and the system resource limit. */ KSystemControl::InitializePhase1(); + /* Synchronize all cores before proceeding, to ensure access to the global rng is consistent. */ + cpu::SynchronizeAllCores(); + /* Initialize the memory manager and the KPageBuffer slabheap. */ { const auto &management_region = KMemoryLayout::GetPoolManagementRegion(); @@ -74,6 +77,9 @@ namespace ams::kern { Kernel::InitializeResourceManagers(pt_heap_region.GetAddress(), pt_heap_region.GetSize()); } + } else { + /* Synchronize all cores before proceeding, to ensure access to the global rng is consistent. */ + cpu::SynchronizeAllCores(); } /* Initialize the supervisor page table for each core. */