From f65c1df0948d00c66eefa583efea6f578ba623b7 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Wed, 13 Jan 2021 13:54:19 +0000 Subject: [PATCH 1/3] Random: Add seeded PRNG --- Source/Core/Common/Random.cpp | 42 ++++++++++++++++++++++++++++++----- Source/Core/Common/Random.h | 25 +++++++++++++++++++++ 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/Source/Core/Common/Random.cpp b/Source/Core/Common/Random.cpp index c512e7695d..754cea397f 100644 --- a/Source/Core/Common/Random.cpp +++ b/Source/Core/Common/Random.cpp @@ -11,10 +11,42 @@ namespace Common::Random { -class CSPRNG final +struct PRNG::Impl +{ + Impl(void* seed, std::size_t size) + { + mbedtls_hmac_drbg_init(&m_context); + const int ret = mbedtls_hmac_drbg_seed_buf( + &m_context, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), static_cast(seed), size); + ASSERT(ret == 0); + } + + ~Impl() { mbedtls_hmac_drbg_free(&m_context); } + + void Generate(void* buffer, std::size_t size) + { + const int ret = mbedtls_hmac_drbg_random(&m_context, static_cast(buffer), size); + ASSERT(ret == 0); + } + + mbedtls_hmac_drbg_context m_context; +}; + +PRNG::PRNG(void* seed, std::size_t size) : m_impl(std::make_unique(seed, size)) +{ +} + +PRNG::~PRNG() = default; + +void PRNG::Generate(void* buffer, std::size_t size) +{ + m_impl->Generate(buffer, size); +} + +class EntropySeededPRNG final { public: - CSPRNG() + EntropySeededPRNG() { mbedtls_entropy_init(&m_entropy); mbedtls_hmac_drbg_init(&m_context); @@ -23,7 +55,7 @@ public: ASSERT(ret == 0); } - ~CSPRNG() + ~EntropySeededPRNG() { mbedtls_hmac_drbg_free(&m_context); mbedtls_entropy_free(&m_entropy); @@ -40,10 +72,10 @@ private: mbedtls_hmac_drbg_context m_context; }; -static thread_local CSPRNG s_csprng; +static thread_local EntropySeededPRNG s_esprng; void Generate(void* buffer, std::size_t size) { - s_csprng.Generate(buffer, size); + s_esprng.Generate(buffer, size); } } // namespace Common::Random diff --git a/Source/Core/Common/Random.h b/Source/Core/Common/Random.h index 1f234f8ac3..789f62d9c1 100644 --- a/Source/Core/Common/Random.h +++ b/Source/Core/Common/Random.h @@ -5,12 +5,37 @@ #pragma once #include +#include #include #include "Common/CommonTypes.h" namespace Common::Random { +/// Cryptographically secure pseudo-random number generator, with explicit seed. +class PRNG final +{ +public: + explicit PRNG(u64 seed) : PRNG(&seed, sizeof(u64)) {} + PRNG(void* seed, std::size_t size); + ~PRNG(); + + void Generate(void* buffer, std::size_t size); + + template + T GenerateValue() + { + static_assert(std::is_arithmetic(), "T must be an arithmetic type in GenerateValue."); + T value; + Generate(&value, sizeof(value)); + return value; + } + +private: + struct Impl; + std::unique_ptr m_impl; +}; + /// Fill `buffer` with random bytes using a cryptographically secure pseudo-random number generator. void Generate(void* buffer, std::size_t size); From fe9207bb56ad87f584d1174582d9ca31d0fb914b Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 3 Jan 2021 19:49:22 +0000 Subject: [PATCH 2/3] UnitTests: Add MOVI2R test --- Source/UnitTests/Core/CMakeLists.txt | 4 + .../Core/PowerPC/JitArm64/MovI2R.cpp | 95 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 Source/UnitTests/Core/PowerPC/JitArm64/MovI2R.cpp diff --git a/Source/UnitTests/Core/CMakeLists.txt b/Source/UnitTests/Core/CMakeLists.txt index c6c9ac4463..01bfd99fbe 100644 --- a/Source/UnitTests/Core/CMakeLists.txt +++ b/Source/UnitTests/Core/CMakeLists.txt @@ -19,4 +19,8 @@ if(_M_X86) PowerPC/Jit64Common/ConvertDoubleToSingle.cpp PowerPC/Jit64Common/Frsqrte.cpp ) +elseif(_M_ARM_64) + add_dolphin_test(PowerPCTest + PowerPC/JitArm64/MovI2R.cpp + ) endif() diff --git a/Source/UnitTests/Core/PowerPC/JitArm64/MovI2R.cpp b/Source/UnitTests/Core/PowerPC/JitArm64/MovI2R.cpp new file mode 100644 index 0000000000..511d1b2d6f --- /dev/null +++ b/Source/UnitTests/Core/PowerPC/JitArm64/MovI2R.cpp @@ -0,0 +1,95 @@ +// Copyright 2021 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#include "Common/Arm64Emitter.h" +#include "Common/Assert.h" +#include "Common/BitUtils.h" +#include "Common/Random.h" + +#include + +namespace +{ +using namespace Arm64Gen; + +class TestMovI2R : public ARM64CodeBlock +{ +public: + TestMovI2R() { AllocCodeSpace(4096); } + + void Check32(u32 value) + { + ResetCodePtr(); + + const u8* fn = GetCodePtr(); + MOVI2R(W0, value); + RET(); + + FlushIcacheSection(const_cast(fn), const_cast(GetCodePtr())); + + const u64 result = Common::BitCast(fn)(); + EXPECT_EQ(value, result); + } + + void Check64(u64 value) + { + ResetCodePtr(); + + const u8* fn = GetCodePtr(); + MOVI2R(X0, value); + RET(); + + FlushIcacheSection(const_cast(fn), const_cast(GetCodePtr())); + + const u64 result = Common::BitCast(fn)(); + EXPECT_EQ(value, result); + } +}; + +} // namespace + +TEST(JitArm64, MovI2R_32BitValues) +{ + TestMovI2R test; + for (u64 i = 0; i < 0x100000000; i++) + { + test.Check32(static_cast(i)); + test.Check64(i); + } +} + +TEST(JitArm64, MovI2R_Rand) +{ + Common::Random::PRNG rng{0}; + TestMovI2R test; + for (u64 i = 0; i < 0x100000; i++) + { + test.Check64(rng.GenerateValue()); + } +} + +TEST(JitArm64, MovI2R_ADP) +{ + TestMovI2R test; + const u64 base = Common::BitCast(test.GetCodePtr()); + for (s64 i = -0x20000; i < 0x20000; i++) + { + const u64 offset = static_cast(i); + test.Check64(base + offset); + } +} + +TEST(JitArm64, MovI2R_ADRP) +{ + TestMovI2R test; + const u64 base = Common::BitCast(test.GetCodePtr()) & ~0xFFF; + for (s64 i = -0x20000; i < 0x20000; i++) + { + const u64 offset = static_cast(i) << 12; + test.Check64(base + offset); + } +} From 1ab7657120cbd9552f89660e23b2d618cc03c4c7 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 31 Jan 2021 13:13:10 +0000 Subject: [PATCH 3/3] MovI2R: Do not exhaustively test --- Source/UnitTests/Core/PowerPC/JitArm64/MovI2R.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/UnitTests/Core/PowerPC/JitArm64/MovI2R.cpp b/Source/UnitTests/Core/PowerPC/JitArm64/MovI2R.cpp index 511d1b2d6f..8f44259f8d 100644 --- a/Source/UnitTests/Core/PowerPC/JitArm64/MovI2R.cpp +++ b/Source/UnitTests/Core/PowerPC/JitArm64/MovI2R.cpp @@ -54,11 +54,13 @@ public: TEST(JitArm64, MovI2R_32BitValues) { + Common::Random::PRNG rng{0}; TestMovI2R test; - for (u64 i = 0; i < 0x100000000; i++) + for (u64 i = 0; i < 0x100000; i++) { - test.Check32(static_cast(i)); - test.Check64(i); + const u32 value = rng.GenerateValue(); + test.Check32(value); + test.Check64(value); } }