diff --git a/src/emulator/serialization_helper.hpp b/src/emulator/serialization_helper.hpp index fbf769c..6af6e0f 100644 --- a/src/emulator/serialization_helper.hpp +++ b/src/emulator/serialization_helper.hpp @@ -19,6 +19,20 @@ inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::steady_ tp = time_point{duration{count}}; } +inline void serialize(utils::buffer_serializer& buffer, const std::chrono::system_clock::time_point& tp) +{ + buffer.write(tp.time_since_epoch().count()); +} + +inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::system_clock::time_point& tp) +{ + using time_point = std::chrono::system_clock::time_point; + using duration = time_point::duration; + + const auto count = buffer.read(); + tp = time_point{duration{count}}; +} + inline void serialize(utils::buffer_serializer& buffer, const std::filesystem::path& path) { buffer.write_string(path.wstring()); diff --git a/src/windows-emulator/kusd_mmio.cpp b/src/windows-emulator/kusd_mmio.cpp index af1d668..dd74db5 100644 --- a/src/windows-emulator/kusd_mmio.cpp +++ b/src/windows-emulator/kusd_mmio.cpp @@ -1,4 +1,5 @@ #include "kusd_mmio.hpp" +#include "syscall_utils.hpp" #include "windows_emulator.hpp" #include @@ -103,6 +104,7 @@ kusd_mmio::kusd_mmio(windows_emulator& win_emu, const bool use_relative_time, co , win_emu_(&win_emu) { setup_kusd(this->kusd_, use_relative_time); + this->start_time_ = convert_from_ksystem_time(this->kusd_.SystemTime); if (perform_registration) { @@ -137,12 +139,14 @@ void kusd_mmio::serialize(utils::buffer_serializer& buffer) const { buffer.write(this->use_relative_time_); buffer.write(this->kusd_); + buffer.write(this->start_time_); } void kusd_mmio::deserialize(utils::buffer_deserializer& buffer) { buffer.read(this->use_relative_time_); buffer.read(this->kusd_); + buffer.read(this->start_time_); this->register_mmio(); } @@ -185,7 +189,22 @@ void kusd_mmio::write(const uint64_t /*addr*/, const size_t /*size*/, const uint void kusd_mmio::update() { - // TODO + auto time = this->start_time_; + + if (this->use_relative_time_) + { + const auto passed_time = this->win_emu_->process().executed_instructions; + const auto clock_frequency = this->kusd_.QpcFrequency; + + using duration = std::chrono::system_clock::duration; + time += duration(passed_time * duration::period::den / clock_frequency); + } + else + { + time = std::chrono::system_clock::now(); + } + + convert_to_ksystem_time(&this->kusd_.SystemTime, time); } void kusd_mmio::register_mmio() diff --git a/src/windows-emulator/kusd_mmio.hpp b/src/windows-emulator/kusd_mmio.hpp index 74e15b1..d122109 100644 --- a/src/windows-emulator/kusd_mmio.hpp +++ b/src/windows-emulator/kusd_mmio.hpp @@ -39,6 +39,7 @@ class kusd_mmio bool use_relative_time_{}; windows_emulator* win_emu_{}; KUSER_SHARED_DATA kusd_{}; + std::chrono::system_clock::time_point start_time_{}; uint64_t read(uint64_t addr, size_t size); void write(uint64_t addr, size_t size, uint64_t data); diff --git a/src/windows-emulator/syscall_utils.hpp b/src/windows-emulator/syscall_utils.hpp index afcd7ba..cb053c0 100644 --- a/src/windows-emulator/syscall_utils.hpp +++ b/src/windows-emulator/syscall_utils.hpp @@ -175,11 +175,12 @@ void write_attribute(emulator& emu, const PS_ATTRIBUTE& attribute, const T& valu } } +constexpr auto HUNDRED_NANOSECONDS_IN_ONE_SECOND = 10000000LL; +constexpr auto EPOCH_DIFFERENCE_1601_TO_1970_SECONDS = 11644473600LL; +constexpr auto WINDOWS_EPOCH_DIFFERENCE = EPOCH_DIFFERENCE_1601_TO_1970_SECONDS * HUNDRED_NANOSECONDS_IN_ONE_SECOND; + inline std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(const LARGE_INTEGER delay_interval) { - constexpr auto HUNDRED_NANOSECONDS_IN_ONE_SECOND = 10000000LL; - constexpr auto EPOCH_DIFFERENCE_1601_TO_1970_SECONDS = 11644473600LL; - if (delay_interval.QuadPart <= 0) { const auto relative_time = -delay_interval.QuadPart; @@ -207,3 +208,38 @@ inline std::chrono::steady_clock::time_point convert_delay_interval_to_time_poin return std::chrono::steady_clock::now() + duration_until_target; } + +inline KSYSTEM_TIME convert_to_ksystem_time(const std::chrono::system_clock::time_point& tp) +{ + const auto duration = tp.time_since_epoch(); + const auto ns_duration = std::chrono::duration_cast(duration); + + const auto total_ticks = ns_duration.count() / 100 + WINDOWS_EPOCH_DIFFERENCE; + + KSYSTEM_TIME time{}; + time.LowPart = static_cast(total_ticks); + time.High1Time = static_cast(total_ticks >> 32); + time.High2Time = time.High1Time; + + return time; +} + +inline void convert_to_ksystem_time(volatile KSYSTEM_TIME* dest, const std::chrono::system_clock::time_point& tp) +{ + const auto time = convert_to_ksystem_time(tp); + memcpy(const_cast(dest), &time, sizeof(*dest)); +} + +inline std::chrono::system_clock::time_point convert_from_ksystem_time(const KSYSTEM_TIME& time) +{ + auto totalTicks = (static_cast(time.High1Time) << 32) | time.LowPart; + totalTicks -= WINDOWS_EPOCH_DIFFERENCE; + + const auto duration = std::chrono::system_clock::duration(totalTicks * 100); + return std::chrono::system_clock::time_point(duration); +} + +inline std::chrono::system_clock::time_point convert_from_ksystem_time(const volatile KSYSTEM_TIME& time) +{ + return convert_from_ksystem_time(*const_cast(&time)); +}