From 082167feeb9b50f209b5364d7936c08695e458f3 Mon Sep 17 00:00:00 2001 From: Merry Date: Sat, 11 Feb 2023 11:01:56 +0000 Subject: [PATCH] backend/arm64: Add InvalidateCacheRanges --- src/dynarmic/CMakeLists.txt | 4 +- .../backend/arm64/a32_address_space.cpp | 11 ++++++ .../backend/arm64/a32_address_space.h | 7 ++++ src/dynarmic/backend/arm64/a32_interface.cpp | 3 +- .../backend/arm64/a64_address_space.cpp | 11 ++++++ .../backend/arm64/a64_address_space.h | 7 ++++ src/dynarmic/backend/arm64/a64_interface.cpp | 37 ++++++++++--------- src/dynarmic/backend/arm64/address_space.cpp | 2 + src/dynarmic/backend/arm64/address_space.h | 1 + .../{x64 => }/block_range_information.cpp | 6 +-- .../{x64 => }/block_range_information.h | 4 +- src/dynarmic/backend/x64/a32_emit_x64.h | 2 +- src/dynarmic/backend/x64/a64_emit_x64.h | 2 +- 13 files changed, 69 insertions(+), 28 deletions(-) rename src/dynarmic/backend/{x64 => }/block_range_information.cpp (91%) rename src/dynarmic/backend/{x64 => }/block_range_information.h (90%) diff --git a/src/dynarmic/CMakeLists.txt b/src/dynarmic/CMakeLists.txt index fc4690f2..36a12cc0 100644 --- a/src/dynarmic/CMakeLists.txt +++ b/src/dynarmic/CMakeLists.txt @@ -1,6 +1,8 @@ include(TargetArchitectureSpecificSources) add_library(dynarmic + backend/block_range_information.cpp + backend/block_range_information.h backend/exception_handler.h common/always_false.h common/cast_util.h @@ -271,8 +273,6 @@ if ("x86_64" IN_LIST ARCHITECTURE) backend/x64/abi.h backend/x64/block_of_code.cpp backend/x64/block_of_code.h - backend/x64/block_range_information.cpp - backend/x64/block_range_information.h backend/x64/callback.cpp backend/x64/callback.h backend/x64/constant_pool.cpp diff --git a/src/dynarmic/backend/arm64/a32_address_space.cpp b/src/dynarmic/backend/arm64/a32_address_space.cpp index 8cf57aaa..2a90d745 100644 --- a/src/dynarmic/backend/arm64/a32_address_space.cpp +++ b/src/dynarmic/backend/arm64/a32_address_space.cpp @@ -181,6 +181,10 @@ IR::Block A32AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const { return ir_block; } +void A32AddressSpace::InvalidateCacheRanges(const boost::icl::interval_set& ranges) { + InvalidateBasicBlocks(block_ranges.InvalidateRanges(ranges)); +} + void A32AddressSpace::EmitPrelude() { using namespace oaknut::util; @@ -392,4 +396,11 @@ EmitConfig A32AddressSpace::GetEmitConfig() { }; } +void A32AddressSpace::RegisterNewBasicBlock(const IR::Block& block, const EmittedBlockInfo&) { + const A32::LocationDescriptor descriptor{block.Location()}; + const A32::LocationDescriptor end_location{block.EndLocation()}; + const auto range = boost::icl::discrete_interval::closed(descriptor.PC(), end_location.PC() - 1); + block_ranges.AddRange(range, descriptor); +} + } // namespace Dynarmic::Backend::Arm64 diff --git a/src/dynarmic/backend/arm64/a32_address_space.h b/src/dynarmic/backend/arm64/a32_address_space.h index e33be9b0..3b9e9fb2 100644 --- a/src/dynarmic/backend/arm64/a32_address_space.h +++ b/src/dynarmic/backend/arm64/a32_address_space.h @@ -6,23 +6,30 @@ #pragma once #include "dynarmic/backend/arm64/address_space.h" +#include "dynarmic/backend/block_range_information.h" #include "dynarmic/interface/A32/config.h" namespace Dynarmic::Backend::Arm64 { +struct EmittedBlockInfo; + class A32AddressSpace final : public AddressSpace { public: explicit A32AddressSpace(const A32::UserConfig& conf); IR::Block GenerateIR(IR::LocationDescriptor) const override; + void InvalidateCacheRanges(const boost::icl::interval_set& ranges); + protected: friend class A32Core; void EmitPrelude(); EmitConfig GetEmitConfig() override; + void RegisterNewBasicBlock(const IR::Block& block, const EmittedBlockInfo& block_info) override; const A32::UserConfig conf; + BlockRangeInformation block_ranges; }; } // namespace Dynarmic::Backend::Arm64 diff --git a/src/dynarmic/backend/arm64/a32_interface.cpp b/src/dynarmic/backend/arm64/a32_interface.cpp index 783e8af8..23753371 100644 --- a/src/dynarmic/backend/arm64/a32_interface.cpp +++ b/src/dynarmic/backend/arm64/a32_interface.cpp @@ -209,8 +209,7 @@ private: } if (!invalid_cache_ranges.empty()) { - // TODO: Optimize - current_address_space.ClearCache(); + current_address_space.InvalidateCacheRanges(invalid_cache_ranges); invalid_cache_ranges.clear(); return; diff --git a/src/dynarmic/backend/arm64/a64_address_space.cpp b/src/dynarmic/backend/arm64/a64_address_space.cpp index 69146a15..9c171b52 100644 --- a/src/dynarmic/backend/arm64/a64_address_space.cpp +++ b/src/dynarmic/backend/arm64/a64_address_space.cpp @@ -350,6 +350,10 @@ IR::Block A64AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const { return ir_block; } +void A64AddressSpace::InvalidateCacheRanges(const boost::icl::interval_set& ranges) { + InvalidateBasicBlocks(block_ranges.InvalidateRanges(ranges)); +} + void A64AddressSpace::EmitPrelude() { using namespace oaknut::util; @@ -568,4 +572,11 @@ EmitConfig A64AddressSpace::GetEmitConfig() { }; } +void A64AddressSpace::RegisterNewBasicBlock(const IR::Block& block, const EmittedBlockInfo&) { + const A64::LocationDescriptor descriptor{block.Location()}; + const A64::LocationDescriptor end_location{block.EndLocation()}; + const auto range = boost::icl::discrete_interval::closed(descriptor.PC(), end_location.PC() - 1); + block_ranges.AddRange(range, descriptor); +} + } // namespace Dynarmic::Backend::Arm64 diff --git a/src/dynarmic/backend/arm64/a64_address_space.h b/src/dynarmic/backend/arm64/a64_address_space.h index 2eadf953..86eae4dd 100644 --- a/src/dynarmic/backend/arm64/a64_address_space.h +++ b/src/dynarmic/backend/arm64/a64_address_space.h @@ -6,23 +6,30 @@ #pragma once #include "dynarmic/backend/arm64/address_space.h" +#include "dynarmic/backend/block_range_information.h" #include "dynarmic/interface/A64/config.h" namespace Dynarmic::Backend::Arm64 { +struct EmittedBlockInfo; + class A64AddressSpace final : public AddressSpace { public: explicit A64AddressSpace(const A64::UserConfig& conf); IR::Block GenerateIR(IR::LocationDescriptor) const override; + void InvalidateCacheRanges(const boost::icl::interval_set& ranges); + protected: friend class A64Core; void EmitPrelude(); EmitConfig GetEmitConfig() override; + void RegisterNewBasicBlock(const IR::Block& block, const EmittedBlockInfo& block_info) override; const A64::UserConfig conf; + BlockRangeInformation block_ranges; }; } // namespace Dynarmic::Backend::Arm64 diff --git a/src/dynarmic/backend/arm64/a64_interface.cpp b/src/dynarmic/backend/arm64/a64_interface.cpp index 0698172c..b80e8b39 100644 --- a/src/dynarmic/backend/arm64/a64_interface.cpp +++ b/src/dynarmic/backend/arm64/a64_interface.cpp @@ -30,7 +30,7 @@ struct Jit::Impl final { HaltReason Run() { ASSERT(!is_executing); - PerformRequestedCacheInvalidation(); + PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); is_executing = true; SCOPE_EXIT { @@ -39,14 +39,14 @@ struct Jit::Impl final { HaltReason hr = core.Run(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(); + PerformRequestedCacheInvalidation(hr); return hr; } HaltReason Step() { ASSERT(!is_executing); - PerformRequestedCacheInvalidation(); + PerformRequestedCacheInvalidation(static_cast(Atomic::Load(&halt_reason))); is_executing = true; SCOPE_EXIT { @@ -55,7 +55,7 @@ struct Jit::Impl final { HaltReason hr = core.Step(current_address_space, current_state, &halt_reason); - PerformRequestedCacheInvalidation(); + PerformRequestedCacheInvalidation(hr); return hr; } @@ -157,23 +157,26 @@ struct Jit::Impl final { } private: - void PerformRequestedCacheInvalidation() { - ClearHalt(HaltReason::CacheInvalidation); + void PerformRequestedCacheInvalidation(HaltReason hr) { + if (Has(hr, HaltReason::CacheInvalidation)) { + std::unique_lock lock{invalidation_mutex}; - if (invalidate_entire_cache) { - current_address_space.ClearCache(); + ClearHalt(HaltReason::CacheInvalidation); - invalidate_entire_cache = false; - invalid_cache_ranges.clear(); - return; - } + if (invalidate_entire_cache) { + current_address_space.ClearCache(); - if (!invalid_cache_ranges.empty()) { - // TODO: Optimize - current_address_space.ClearCache(); + invalidate_entire_cache = false; + invalid_cache_ranges.clear(); + return; + } - invalid_cache_ranges.clear(); - return; + if (!invalid_cache_ranges.empty()) { + current_address_space.InvalidateCacheRanges(invalid_cache_ranges); + + invalid_cache_ranges.clear(); + return; + } } } diff --git a/src/dynarmic/backend/arm64/address_space.cpp b/src/dynarmic/backend/arm64/address_space.cpp index d42380cb..402932bc 100644 --- a/src/dynarmic/backend/arm64/address_space.cpp +++ b/src/dynarmic/backend/arm64/address_space.cpp @@ -115,6 +115,8 @@ EmittedBlockInfo AddressSpace::Emit(IR::Block block) { mem.invalidate(reinterpret_cast(block_info.entry_point), block_info.size); mem.protect(); + RegisterNewBasicBlock(block, block_info); + return block_info; } diff --git a/src/dynarmic/backend/arm64/address_space.h b/src/dynarmic/backend/arm64/address_space.h index 04f41750..54a0f91f 100644 --- a/src/dynarmic/backend/arm64/address_space.h +++ b/src/dynarmic/backend/arm64/address_space.h @@ -45,6 +45,7 @@ public: protected: virtual EmitConfig GetEmitConfig() = 0; + virtual void RegisterNewBasicBlock(const IR::Block& block, const EmittedBlockInfo& block_info) = 0; size_t GetRemainingSize(); EmittedBlockInfo Emit(IR::Block ir_block); diff --git a/src/dynarmic/backend/x64/block_range_information.cpp b/src/dynarmic/backend/block_range_information.cpp similarity index 91% rename from src/dynarmic/backend/x64/block_range_information.cpp rename to src/dynarmic/backend/block_range_information.cpp index c590db12..47e512f5 100644 --- a/src/dynarmic/backend/x64/block_range_information.cpp +++ b/src/dynarmic/backend/block_range_information.cpp @@ -3,14 +3,14 @@ * SPDX-License-Identifier: 0BSD */ -#include "dynarmic/backend/x64/block_range_information.h" +#include "dynarmic/backend/block_range_information.h" #include #include #include #include -namespace Dynarmic::Backend::X64 { +namespace Dynarmic::Backend { template void BlockRangeInformation::AddRange(boost::icl::discrete_interval range, IR::LocationDescriptor location) { @@ -40,4 +40,4 @@ tsl::robin_set BlockRangeInformation template class BlockRangeInformation; template class BlockRangeInformation; -} // namespace Dynarmic::Backend::X64 +} // namespace Dynarmic::Backend diff --git a/src/dynarmic/backend/x64/block_range_information.h b/src/dynarmic/backend/block_range_information.h similarity index 90% rename from src/dynarmic/backend/x64/block_range_information.h rename to src/dynarmic/backend/block_range_information.h index a3d43f2b..3402b155 100644 --- a/src/dynarmic/backend/x64/block_range_information.h +++ b/src/dynarmic/backend/block_range_information.h @@ -13,7 +13,7 @@ #include "dynarmic/ir/location_descriptor.h" -namespace Dynarmic::Backend::X64 { +namespace Dynarmic::Backend { template class BlockRangeInformation { @@ -26,4 +26,4 @@ private: boost::icl::interval_map> block_ranges; }; -} // namespace Dynarmic::Backend::X64 +} // namespace Dynarmic::Backend diff --git a/src/dynarmic/backend/x64/a32_emit_x64.h b/src/dynarmic/backend/x64/a32_emit_x64.h index 4866c9ec..3706b30a 100644 --- a/src/dynarmic/backend/x64/a32_emit_x64.h +++ b/src/dynarmic/backend/x64/a32_emit_x64.h @@ -12,8 +12,8 @@ #include +#include "dynarmic/backend/block_range_information.h" #include "dynarmic/backend/x64/a32_jitstate.h" -#include "dynarmic/backend/x64/block_range_information.h" #include "dynarmic/backend/x64/emit_x64.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/interface/A32/a32.h" diff --git a/src/dynarmic/backend/x64/a64_emit_x64.h b/src/dynarmic/backend/x64/a64_emit_x64.h index bd0e6e01..ed493155 100644 --- a/src/dynarmic/backend/x64/a64_emit_x64.h +++ b/src/dynarmic/backend/x64/a64_emit_x64.h @@ -10,8 +10,8 @@ #include #include +#include "dynarmic/backend/block_range_information.h" #include "dynarmic/backend/x64/a64_jitstate.h" -#include "dynarmic/backend/x64/block_range_information.h" #include "dynarmic/backend/x64/emit_x64.h" #include "dynarmic/frontend/A64/a64_location_descriptor.h" #include "dynarmic/interface/A64/a64.h"