Seregon/ShadPKG

A tool for deriving PKG packet encryption keys for ps4 written in c++

C++/47.3 KB/No license
common/rdtsc.cpp
ShadPKG / common / rdtsc.cpp
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3 
4#include <thread>
5#include "common/rdtsc.h"
6#include "common/uint128.h"
7 
8#ifdef _WIN64
9#include <windows.h>
10#endif
11 
12namespace Common {
13 
14static constexpr size_t SecondToNanoseconds = 1000000000ULL;
15 
16template <u64 Nearest>
17static u64 RoundToNearest(u64 value) {
18 const auto mod = value % Nearest;
19 return mod >= (Nearest / 2) ? (value - mod + Nearest) : (value - mod);
20}
21 
22static u64 GetTimeNs() {
23#ifdef _WIN64
24 // GetSystemTimePreciseAsFileTime returns the file time in 100ns units.
25 static constexpr u64 Multiplier = 100;
26 // Convert Windows epoch to Unix epoch.
27 static constexpr u64 WindowsEpochToUnixEpoch = 0x19DB1DED53E8000LL;
28 FILETIME filetime;
29 GetSystemTimePreciseAsFileTime(&filetime);
30 return Multiplier * ((static_cast<u64>(filetime.dwHighDateTime) << 32) +
31 static_cast<u64>(filetime.dwLowDateTime) - WindowsEpochToUnixEpoch);
32#elif defined(__APPLE__)
33 return clock_gettime_nsec_np(CLOCK_REALTIME);
34#else
35 timespec ts;
36 clock_gettime(CLOCK_REALTIME, &ts);
37 return ts.tv_sec * SecondToNanoseconds + ts.tv_nsec;
38#endif
39}
40 
41u64 EstimateRDTSCFrequency() {
42 // Discard the first result measuring the rdtsc.
43 FencedRDTSC();
44 std::this_thread::sleep_for(std::chrono::milliseconds{1});
45 FencedRDTSC();
46 
47 // Get the current time.
48 const auto start_time = GetTimeNs();
49 const u64 tsc_start = FencedRDTSC();
50 // Wait for 100 milliseconds.
51 std::this_thread::sleep_for(std::chrono::milliseconds{100});
52 const auto end_time = GetTimeNs();
53 const u64 tsc_end = FencedRDTSC();
54 // Calculate differences.
55 const u64 tsc_diff = tsc_end - tsc_start;
56 const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, end_time - start_time);
57 return RoundToNearest<100'000>(tsc_freq);
58}
59 
60} // namespace Common
61