lru fix by wildcard
Some checks failed
eden-license / license-header (pull_request) Failing after 20s
Some checks failed
eden-license / license-header (pull_request) Failing after 20s
This commit is contained in:
parent
7249bc0d22
commit
390280476c
2 changed files with 33 additions and 12 deletions
|
@ -16,6 +16,24 @@
|
||||||
#include "core/hle/kernel/physical_memory.h"
|
#include "core/hle/kernel/physical_memory.h"
|
||||||
#include "lru_cache.h"
|
#include "lru_cache.h"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
using ModuleID = std::array<u8, 32>; // NSO build ID
|
||||||
|
struct PatchCacheKey {
|
||||||
|
ModuleID module_id;
|
||||||
|
uintptr_t offset;
|
||||||
|
bool operator==(const PatchCacheKey&) const = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct std::hash<PatchCacheKey> {
|
||||||
|
size_t operator()(const PatchCacheKey& key) const {
|
||||||
|
// Simple XOR hash of first few bytes
|
||||||
|
size_t hash = 0;
|
||||||
|
for (size_t i = 0; i < key.module_id.size(); ++i) {
|
||||||
|
hash ^= static_cast<size_t>(key.module_id[i]) << ((i % sizeof(size_t)) * 8);
|
||||||
|
}
|
||||||
|
return hash ^ std::hash<uintptr_t>{}(key.offset);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
namespace Core::NCE {
|
namespace Core::NCE {
|
||||||
|
|
||||||
|
@ -31,13 +49,15 @@ using EntryTrampolines = std::unordered_map<ModuleTextAddress, PatchTextAddress>
|
||||||
|
|
||||||
class Patcher {
|
class Patcher {
|
||||||
public:
|
public:
|
||||||
|
void SetModuleID(const ModuleID& id) {
|
||||||
|
module_id = id;
|
||||||
|
}
|
||||||
Patcher(const Patcher&) = delete;
|
Patcher(const Patcher&) = delete;
|
||||||
Patcher& operator=(const Patcher&) = delete;
|
Patcher& operator=(const Patcher&) = delete;
|
||||||
Patcher(Patcher&& other) noexcept;
|
Patcher(Patcher&& other) noexcept;
|
||||||
Patcher& operator=(Patcher&&) noexcept = delete;
|
Patcher& operator=(Patcher&&) noexcept = delete;
|
||||||
explicit Patcher();
|
explicit Patcher();
|
||||||
~Patcher();
|
~Patcher();
|
||||||
|
|
||||||
bool PatchText(const Kernel::PhysicalMemory& program_image,
|
bool PatchText(const Kernel::PhysicalMemory& program_image,
|
||||||
const Kernel::CodeSet::Segment& code);
|
const Kernel::CodeSet::Segment& code);
|
||||||
bool RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code,
|
bool RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code,
|
||||||
|
@ -50,7 +70,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using ModuleDestLabel = uintptr_t;
|
using ModuleDestLabel = uintptr_t;
|
||||||
|
ModuleID module_id{};
|
||||||
struct Trampoline {
|
struct Trampoline {
|
||||||
ptrdiff_t patch_offset;
|
ptrdiff_t patch_offset;
|
||||||
uintptr_t module_offset;
|
uintptr_t module_offset;
|
||||||
|
@ -68,26 +88,25 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t CACHE_SIZE = 16384; // Cache size for patch entries
|
static constexpr size_t CACHE_SIZE = 16384; // Cache size for patch entries
|
||||||
LRUCache<uintptr_t, PatchTextAddress> patch_cache{CACHE_SIZE, Settings::values.lru_cache_enabled.GetValue()};
|
LRUCache<PatchCacheKey, PatchTextAddress> patch_cache{CACHE_SIZE, Settings::values.lru_cache_enabled.GetValue()};
|
||||||
|
|
||||||
void BranchToPatch(uintptr_t module_dest) {
|
void BranchToPatch(uintptr_t module_dest) {
|
||||||
if (patch_cache.isEnabled()) {
|
if (patch_cache.isEnabled()) {
|
||||||
LOG_DEBUG(Core_ARM, "LRU cache lookup for address {:#x}", module_dest);
|
PatchCacheKey key{module_id, module_dest};
|
||||||
|
LOG_DEBUG(Core_ARM, "LRU cache lookup for module={}, offset={:#x}", fmt::ptr(module_id.data()), module_dest);
|
||||||
// Try to get existing patch entry from cache
|
// Try to get existing patch entry from cache
|
||||||
if (auto* cached_patch = patch_cache.get(module_dest)) {
|
if (auto* cached_patch = patch_cache.get(key)) {
|
||||||
LOG_WARNING(Core_ARM, "LRU cache hit for address {:#x}", module_dest);
|
LOG_WARNING(Core_ARM, "LRU cache hit for module offset {:#x}", module_dest);
|
||||||
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), *cached_patch});
|
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), *cached_patch});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_DEBUG(Core_ARM, "LRU cache miss for address {:#x}, creating new patch", module_dest);
|
LOG_DEBUG(Core_ARM, "LRU cache miss for module offset {:#x}, creating new patch", module_dest);
|
||||||
|
// Not in cache: create and store
|
||||||
// If not in cache, create new entry and cache it
|
|
||||||
const auto patch_addr = c.offset();
|
const auto patch_addr = c.offset();
|
||||||
curr_patch->m_branch_to_patch_relocations.push_back({patch_addr, module_dest});
|
curr_patch->m_branch_to_patch_relocations.push_back({patch_addr, module_dest});
|
||||||
patch_cache.put(module_dest, patch_addr);
|
patch_cache.put(key, patch_addr);
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG(Core_ARM, "LRU cache disabled - creating direct patch for address {:#x}", module_dest);
|
LOG_DEBUG(Core_ARM, "LRU cache disabled - direct patch for offset {:#x}", module_dest);
|
||||||
// LRU disabled - use pre-LRU approach
|
|
||||||
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), module_dest});
|
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), module_dest});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
|
||||||
const auto& code = codeset.CodeSegment();
|
const auto& code = codeset.CodeSegment();
|
||||||
auto* patch = patches ? &patches->operator[](patch_index) : nullptr;
|
auto* patch = patches ? &patches->operator[](patch_index) : nullptr;
|
||||||
if (patch && !load_into_process) {
|
if (patch && !load_into_process) {
|
||||||
|
//Set module ID using build_id from the NSO header
|
||||||
|
patch->SetModuleID(nso_header.build_id);
|
||||||
// Patch SVCs and MRS calls in the guest code
|
// Patch SVCs and MRS calls in the guest code
|
||||||
while (!patch->PatchText(program_image, code)) {
|
while (!patch->PatchText(program_image, code)) {
|
||||||
patch = &patches->emplace_back();
|
patch = &patches->emplace_back();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue