diff options
Diffstat (limited to '')
85 files changed, 625 insertions, 460 deletions
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index 8bc6a4a04..c23b2f19e 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -449,7 +449,7 @@ private: loader->ReadTitle(entry.title); loader->ReadIcon(entry.icon); if (loader->GetFileType() == Loader::FileType::NRO) { - jauto loader_nro = dynamic_cast<Loader::AppLoader_NRO*>(loader.get()); + jauto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get()); entry.isHomebrew = loader_nro->IsHomebrew(); } else { entry.isHomebrew = false; diff --git a/src/common/demangle.cpp b/src/common/demangle.cpp index 3310faf86..6e117cb41 100644 --- a/src/common/demangle.cpp +++ b/src/common/demangle.cpp @@ -23,7 +23,7 @@ std::string DemangleSymbol(const std::string& mangled) { SCOPE_EXIT({ std::free(demangled); }); if (is_itanium(mangled)) { - demangled = llvm::itaniumDemangle(mangled.c_str(), nullptr, nullptr, nullptr); + demangled = llvm::itaniumDemangle(mangled.c_str()); } if (!demangled) { diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp index da64848da..f2ed795cc 100644 --- a/src/common/detached_tasks.cpp +++ b/src/common/detached_tasks.cpp @@ -30,8 +30,8 @@ DetachedTasks::~DetachedTasks() { void DetachedTasks::AddTask(std::function<void()> task) { std::unique_lock lock{instance->mutex}; ++instance->count; - std::thread([task{std::move(task)}]() { - task(); + std::thread([task_{std::move(task)}]() { + task_(); std::unique_lock thread_lock{instance->mutex}; --instance->count; std::notify_all_at_thread_exit(instance->cv, std::move(thread_lock)); diff --git a/src/common/page_table.h b/src/common/page_table.h index fec8378f3..e653d52ad 100644 --- a/src/common/page_table.h +++ b/src/common/page_table.h @@ -51,7 +51,7 @@ struct PageTable { class PageInfo { public: /// Returns the page pointer - [[nodiscard]] u8* Pointer() const noexcept { + [[nodiscard]] uintptr_t Pointer() const noexcept { return ExtractPointer(raw.load(std::memory_order_relaxed)); } @@ -61,7 +61,7 @@ struct PageTable { } /// Returns the page pointer and attribute pair, extracted from the same atomic read - [[nodiscard]] std::pair<u8*, PageType> PointerType() const noexcept { + [[nodiscard]] std::pair<uintptr_t, PageType> PointerType() const noexcept { const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed); return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)}; } @@ -73,13 +73,13 @@ struct PageTable { } /// Write a page pointer and type pair atomically - void Store(u8* pointer, PageType type) noexcept { - raw.store(reinterpret_cast<uintptr_t>(pointer) | static_cast<uintptr_t>(type)); + void Store(uintptr_t pointer, PageType type) noexcept { + raw.store(pointer | static_cast<uintptr_t>(type)); } /// Unpack a pointer from a page info raw representation - [[nodiscard]] static u8* ExtractPointer(uintptr_t raw) noexcept { - return reinterpret_cast<u8*>(raw & (~uintptr_t{0} << ATTRIBUTE_BITS)); + [[nodiscard]] static uintptr_t ExtractPointer(uintptr_t raw) noexcept { + return raw & (~uintptr_t{0} << ATTRIBUTE_BITS); } /// Unpack a page type from a page info raw representation diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 5972480e5..d4e55f988 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -26,7 +26,8 @@ std::string GetTimeZoneString() { std::string location_name; if (time_zone_index == 0) { // Auto -#if __cpp_lib_chrono >= 201907L +#if __cpp_lib_chrono >= 201907L && !defined(MINGW) + // Disabled for MinGW -- tzdb always returns Etc/UTC try { const struct std::chrono::tzdb& time_zone_data = std::chrono::get_tzdb(); const std::chrono::time_zone* current_zone = time_zone_data.current_zone(); diff --git a/src/common/time_zone.cpp b/src/common/time_zone.cpp index d8d7896c6..69e728a9d 100644 --- a/src/common/time_zone.cpp +++ b/src/common/time_zone.cpp @@ -4,13 +4,13 @@ #include <chrono> #include <exception> #include <iomanip> +#include <map> #include <sstream> #include <stdexcept> #include <fmt/chrono.h> #include <fmt/core.h> #include "common/logging/log.h" -#include "common/settings.h" #include "common/time_zone.h" namespace Common::TimeZone { @@ -33,32 +33,29 @@ std::string GetDefaultTimeZone() { return "GMT"; } -static std::string GetOsTimeZoneOffset() { - const std::time_t t{std::time(nullptr)}; - const std::tm tm{*std::localtime(&t)}; - - return fmt::format("{:%z}", tm); -} - -static int ConvertOsTimeZoneOffsetToInt(const std::string& timezone) { - try { - return std::stoi(timezone); - } catch (const std::invalid_argument&) { - LOG_CRITICAL(Common, "invalid_argument with {}!", timezone); - return 0; - } catch (const std::out_of_range&) { - LOG_CRITICAL(Common, "out_of_range with {}!", timezone); - return 0; - } +// Results are not comparable to seconds since Epoch +static std::time_t TmSpecToSeconds(const struct std::tm& spec) { + const int year = spec.tm_year - 1; // Years up to now + const int leap_years = year / 4 - year / 100; + std::time_t cumulative = spec.tm_year; + cumulative = cumulative * 365 + leap_years + spec.tm_yday; // Years to days + cumulative = cumulative * 24 + spec.tm_hour; // Days to hours + cumulative = cumulative * 60 + spec.tm_min; // Hours to minutes + cumulative = cumulative * 60 + spec.tm_sec; // Minutes to seconds + return cumulative; } std::chrono::seconds GetCurrentOffsetSeconds() { - const int offset{ConvertOsTimeZoneOffsetToInt(GetOsTimeZoneOffset())}; + const std::time_t t{std::time(nullptr)}; + const std::tm local{*std::localtime(&t)}; + const std::tm gmt{*std::gmtime(&t)}; - int seconds{(offset / 100) * 60 * 60}; // Convert hour component to seconds - seconds += (offset % 100) * 60; // Convert minute component to seconds + // gmt_seconds is a different offset than time(nullptr) + const auto gmt_seconds = TmSpecToSeconds(gmt); + const auto local_seconds = TmSpecToSeconds(local); + const auto seconds_offset = local_seconds - gmt_seconds; - return std::chrono::seconds{seconds}; + return std::chrono::seconds{seconds_offset}; } // Key is [Hours * 100 + Minutes], multiplied by 100 if DST @@ -71,11 +68,6 @@ const static std::map<s64, const char*> off_timezones = { }; std::string FindSystemTimeZone() { -#if defined(MINGW) - // MinGW has broken strftime -- https://sourceforge.net/p/mingw-w64/bugs/793/ - // e.g. fmt::format("{:%z}") -- returns "Eastern Daylight Time" when it should be "-0400" - return timezones[0]; -#else const s64 seconds = static_cast<s64>(GetCurrentOffsetSeconds().count()); const s64 minutes = seconds / 60; @@ -97,7 +89,6 @@ std::string FindSystemTimeZone() { } } return fmt::format("Etc/GMT{:s}{:d}", hours > 0 ? "-" : "+", std::abs(hours)); -#endif } } // namespace Common::TimeZone diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index aa0eb9791..0c012f094 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp @@ -217,8 +217,8 @@ void ARM_Interface::Run() { } } -void ARM_Interface::LoadWatchpointArray(const WatchpointArray& wp) { - watchpoints = ℘ +void ARM_Interface::LoadWatchpointArray(const WatchpointArray* wp) { + watchpoints = wp; } const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint( diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index d5f2fa09a..3d866ff6f 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -186,7 +186,7 @@ public: virtual void SaveContext(ThreadContext64& ctx) const = 0; virtual void LoadContext(const ThreadContext32& ctx) = 0; virtual void LoadContext(const ThreadContext64& ctx) = 0; - void LoadWatchpointArray(const WatchpointArray& wp); + void LoadWatchpointArray(const WatchpointArray* wp); /// Clears the exclusive monitor's state. virtual void ClearExclusiveState() = 0; diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 3b82fb73c..c97158a71 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -346,11 +346,11 @@ void ARM_Dynarmic_32::RewindBreakpointInstruction() { } ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, - ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) + DynarmicExclusiveMonitor& exclusive_monitor_, + std::size_t core_index_) : ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)), cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_}, - exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, - null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {} + exclusive_monitor{exclusive_monitor_}, null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {} ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index a990845cb..92fb3f836 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h @@ -12,7 +12,7 @@ #include "common/common_types.h" #include "common/hash.h" #include "core/arm/arm_interface.h" -#include "core/arm/exclusive_monitor.h" +#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" namespace Core::Memory { class Memory; @@ -28,8 +28,8 @@ class System; class ARM_Dynarmic_32 final : public ARM_Interface { public: - ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, - std::size_t core_index_); + ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, + DynarmicExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); ~ARM_Dynarmic_32() override; void SetPC(u64 pc) override; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index bb97ed5bc..791d466ca 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -405,11 +405,11 @@ void ARM_Dynarmic_64::RewindBreakpointInstruction() { } ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, - ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) + DynarmicExclusiveMonitor& exclusive_monitor_, + std::size_t core_index_) : ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_}, - exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, - null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {} + exclusive_monitor{exclusive_monitor_}, null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {} ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index af2aa1f1c..2b88a08e2 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h @@ -11,7 +11,7 @@ #include "common/common_types.h" #include "common/hash.h" #include "core/arm/arm_interface.h" -#include "core/arm/exclusive_monitor.h" +#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" namespace Core::Memory { class Memory; @@ -25,8 +25,8 @@ class System; class ARM_Dynarmic_64 final : public ARM_Interface { public: - ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, - std::size_t core_index_); + ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, + DynarmicExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); ~ARM_Dynarmic_64() override; void SetPC(u64 pc) override; diff --git a/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h index 57e6dd0d0..fbfcd8d95 100644 --- a/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h +++ b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h @@ -6,8 +6,6 @@ #include <dynarmic/interface/exclusive_monitor.h> #include "common/common_types.h" -#include "core/arm/dynarmic/arm_dynarmic_32.h" -#include "core/arm/dynarmic/arm_dynarmic_64.h" #include "core/arm/exclusive_monitor.h" namespace Core::Memory { @@ -16,6 +14,9 @@ class Memory; namespace Core { +class ARM_Dynarmic_32; +class ARM_Dynarmic_64; + class DynarmicExclusiveMonitor final : public ExclusiveMonitor { public: explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_); diff --git a/src/core/core.cpp b/src/core/core.cpp index 9e3eb3795..48233d7c8 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -880,6 +880,14 @@ const FileSys::ContentProvider& System::GetContentProvider() const { return *impl->content_provider; } +FileSys::ContentProviderUnion& System::GetContentProviderUnion() { + return *impl->content_provider; +} + +const FileSys::ContentProviderUnion& System::GetContentProviderUnion() const { + return *impl->content_provider; +} + Service::FileSystem::FileSystemController& System::GetFileSystemController() { return impl->fs_controller; } diff --git a/src/core/core.h b/src/core/core.h index 14b2f7785..c70ea1965 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -381,6 +381,9 @@ public: [[nodiscard]] FileSys::ContentProvider& GetContentProvider(); [[nodiscard]] const FileSys::ContentProvider& GetContentProvider() const; + [[nodiscard]] FileSys::ContentProviderUnion& GetContentProviderUnion(); + [[nodiscard]] const FileSys::ContentProviderUnion& GetContentProviderUnion() const; + [[nodiscard]] Service::FileSystem::FileSystemController& GetFileSystemController(); [[nodiscard]] const Service::FileSystem::FileSystemController& GetFileSystemController() const; diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index e2a13bbd2..0f839d5b4 100644 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp @@ -261,10 +261,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction const size_t addr{static_cast<size_t>(strtoll(command.data(), nullptr, 16))}; const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))}; - if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { - std::vector<u8> mem(size); - system.ApplicationMemory().ReadBlock(addr, mem.data(), size); - + std::vector<u8> mem(size); + if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) { SendReply(Common::HexToString(mem)); } else { SendReply(GDB_STUB_REPLY_ERR); @@ -281,8 +279,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction const auto mem_substr{std::string_view(command).substr(mem_sep)}; const auto mem{Common::HexStringToVector(mem_substr, false)}; - if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) { - system.ApplicationMemory().WriteBlock(addr, mem.data(), size); + if (system.ApplicationMemory().WriteBlock(addr, mem.data(), size)) { system.InvalidateCpuInstructionCacheRange(addr, size); SendReply(GDB_STUB_REPLY_OK); } else { @@ -556,7 +553,7 @@ void GDBStub::HandleQuery(std::string_view command) { } else { SendReply(fmt::format( "TextSeg={:x}", - GetInteger(system.ApplicationProcess()->PageTable().GetCodeRegionStart()))); + GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart()))); } } else if (command.starts_with("Xfer:libraries:read::")) { Loader::AppLoader::Modules modules; @@ -731,7 +728,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) { std::string reply; auto* process = system.ApplicationProcess(); - auto& page_table = process->PageTable(); + auto& page_table = process->GetPageTable(); const char* commands = "Commands:\n" " get fastmem\n" diff --git a/src/core/hle/kernel/k_auto_object.cpp b/src/core/hle/kernel/k_auto_object.cpp index 0ae42c95c..9cd7a9fd5 100644 --- a/src/core/hle/kernel/k_auto_object.cpp +++ b/src/core/hle/kernel/k_auto_object.cpp @@ -15,8 +15,8 @@ void KAutoObject::RegisterWithKernel() { m_kernel.RegisterKernelObject(this); } -void KAutoObject::UnregisterWithKernel() { - m_kernel.UnregisterKernelObject(this); +void KAutoObject::UnregisterWithKernel(KernelCore& kernel, KAutoObject* self) { + kernel.UnregisterKernelObject(self); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index f384b1568..8d4e0df44 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h @@ -159,14 +159,15 @@ public: // If ref count hits zero, destroy the object. if (cur_ref_count - 1 == 0) { + KernelCore& kernel = m_kernel; this->Destroy(); - this->UnregisterWithKernel(); + KAutoObject::UnregisterWithKernel(kernel, this); } } private: void RegisterWithKernel(); - void UnregisterWithKernel(); + static void UnregisterWithKernel(KernelCore& kernel, KAutoObject* self); protected: KernelCore& m_kernel; diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp index 3583bee44..7454be55c 100644 --- a/src/core/hle/kernel/k_code_memory.cpp +++ b/src/core/hle/kernel/k_code_memory.cpp @@ -25,7 +25,7 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddres m_owner = GetCurrentProcessPointer(m_kernel); // Get the owner page table. - auto& page_table = m_owner->PageTable(); + auto& page_table = m_owner->GetPageTable(); // Construct the page group. m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager()); @@ -53,7 +53,7 @@ void KCodeMemory::Finalize() { // Unlock. if (!m_is_mapped && !m_is_owner_mapped) { const size_t size = m_page_group->GetNumPages() * PageSize; - m_owner->PageTable().UnlockForCodeMemory(m_address, size, *m_page_group); + m_owner->GetPageTable().UnlockForCodeMemory(m_address, size, *m_page_group); } // Close the page group. @@ -75,7 +75,7 @@ Result KCodeMemory::Map(KProcessAddress address, size_t size) { R_UNLESS(!m_is_mapped, ResultInvalidState); // Map the memory. - R_TRY(GetCurrentProcess(m_kernel).PageTable().MapPageGroup( + R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup( address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite)); // Mark ourselves as mapped. @@ -92,8 +92,8 @@ Result KCodeMemory::Unmap(KProcessAddress address, size_t size) { KScopedLightLock lk(m_lock); // Unmap the memory. - R_TRY(GetCurrentProcess(m_kernel).PageTable().UnmapPageGroup(address, *m_page_group, - KMemoryState::CodeOut)); + R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, + KMemoryState::CodeOut)); // Mark ourselves as unmapped. m_is_mapped = false; @@ -126,8 +126,8 @@ Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::Memory } // Map the memory. - R_TRY(m_owner->PageTable().MapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode, - k_perm)); + R_TRY(m_owner->GetPageTable().MapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode, + k_perm)); // Mark ourselves as mapped. m_is_owner_mapped = true; @@ -143,7 +143,8 @@ Result KCodeMemory::UnmapFromOwner(KProcessAddress address, size_t size) { KScopedLightLock lk(m_lock); // Unmap the memory. - R_TRY(m_owner->PageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode)); + R_TRY(m_owner->GetPageTable().UnmapPageGroup(address, *m_page_group, + KMemoryState::GeneratedCode)); // Mark ourselves as unmapped. m_is_owner_mapped = false; diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index 022d15f35..b9e8c6042 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h @@ -388,39 +388,6 @@ public: constexpr size_t GetHeapSize() const { return m_current_heap_end - m_heap_region_start; } - constexpr bool IsInsideAddressSpace(KProcessAddress address, size_t size) const { - return m_address_space_start <= address && address + size - 1 <= m_address_space_end - 1; - } - constexpr bool IsOutsideAliasRegion(KProcessAddress address, size_t size) const { - return m_alias_region_start > address || address + size - 1 > m_alias_region_end - 1; - } - constexpr bool IsOutsideStackRegion(KProcessAddress address, size_t size) const { - return m_stack_region_start > address || address + size - 1 > m_stack_region_end - 1; - } - constexpr bool IsInvalidRegion(KProcessAddress address, size_t size) const { - return address + size - 1 > GetAliasCodeRegionStart() + GetAliasCodeRegionSize() - 1; - } - constexpr bool IsInsideHeapRegion(KProcessAddress address, size_t size) const { - return address + size > m_heap_region_start && m_heap_region_end > address; - } - constexpr bool IsInsideAliasRegion(KProcessAddress address, size_t size) const { - return address + size > m_alias_region_start && m_alias_region_end > address; - } - constexpr bool IsOutsideASLRRegion(KProcessAddress address, size_t size) const { - if (IsInvalidRegion(address, size)) { - return true; - } - if (IsInsideHeapRegion(address, size)) { - return true; - } - if (IsInsideAliasRegion(address, size)) { - return true; - } - return {}; - } - constexpr bool IsInsideASLRRegion(KProcessAddress address, size_t size) const { - return !IsOutsideASLRRegion(address, size); - } constexpr size_t GetNumGuardPages() const { return IsKernel() ? 1 : 4; } @@ -436,6 +403,14 @@ public: return m_address_space_start <= addr && addr < addr + size && addr + size - 1 <= m_address_space_end - 1; } + constexpr bool IsInAliasRegion(KProcessAddress addr, size_t size) const { + return this->Contains(addr, size) && m_alias_region_start <= addr && + addr + size - 1 <= m_alias_region_end - 1; + } + constexpr bool IsInHeapRegion(KProcessAddress addr, size_t size) const { + return this->Contains(addr, size) && m_heap_region_start <= addr && + addr + size - 1 <= m_heap_region_end - 1; + } public: static KVirtualAddress GetLinearMappedVirtualAddress(const KMemoryLayout& layout, diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index efe86ad27..44c7cb22f 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -38,7 +38,7 @@ namespace { */ void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, KProcessAddress stack_top) { - const KProcessAddress entry_point = owner_process.PageTable().GetCodeRegionStart(); + const KProcessAddress entry_point = owner_process.GetPageTable().GetCodeRegionStart(); ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1)); KThread* thread = KThread::Create(system.Kernel()); diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 925981d06..c9b37e138 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -110,16 +110,6 @@ public: ProcessType type, KResourceLimit* res_limit); /// Gets a reference to the process' page table. - KPageTable& PageTable() { - return m_page_table; - } - - /// Gets const a reference to the process' page table. - const KPageTable& PageTable() const { - return m_page_table; - } - - /// Gets a reference to the process' page table. KPageTable& GetPageTable() { return m_page_table; } diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 75ce5a23c..d8143c650 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -510,11 +510,12 @@ void KScheduler::Unload(KThread* thread) { void KScheduler::Reload(KThread* thread) { auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); + auto* process = thread->GetOwnerProcess(); cpu_core.LoadContext(thread->GetContext32()); cpu_core.LoadContext(thread->GetContext64()); cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress())); cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0()); - cpu_core.LoadWatchpointArray(thread->GetOwnerProcess()->GetWatchpoints()); + cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr); cpu_core.ClearExclusiveState(); } diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index efb5699de..f713968f6 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp @@ -90,8 +90,8 @@ Result KSharedMemory::Map(KProcess& target_process, KProcessAddress address, std R_UNLESS(map_perm == test_perm, ResultInvalidNewMemoryPermission); } - R_RETURN(target_process.PageTable().MapPageGroup(address, *m_page_group, KMemoryState::Shared, - ConvertToKMemoryPermission(map_perm))); + R_RETURN(target_process.GetPageTable().MapPageGroup( + address, *m_page_group, KMemoryState::Shared, ConvertToKMemoryPermission(map_perm))); } Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address, @@ -100,7 +100,7 @@ Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address, R_UNLESS(m_size == unmap_size, ResultInvalidSize); R_RETURN( - target_process.PageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::Shared)); + target_process.GetPageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::Shared)); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index adb6ec581..7df8fd7f7 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -129,7 +129,7 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress case ThreadType::User: ASSERT(((owner == nullptr) || (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask())); - ASSERT(((owner == nullptr) || + ASSERT(((owner == nullptr) || (prio > Svc::LowestThreadPriority) || (owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask())); break; case ThreadType::Kernel: @@ -302,12 +302,12 @@ Result KThread::InitializeServiceThread(Core::System& system, KThread* thread, std::function<void()>&& func, s32 prio, s32 virt_core, KProcess* owner) { system.Kernel().GlobalSchedulerContext().AddThread(thread); - std::function<void()> func2{[&system, func{std::move(func)}] { + std::function<void()> func2{[&system, func_{std::move(func)}] { // Similar to UserModeThreadStarter. system.Kernel().CurrentScheduler()->OnThreadStart(); // Run the guest function. - func(); + func_(); // Exit. Svc::ExitThread(system); diff --git a/src/core/hle/kernel/k_thread_local_page.cpp b/src/core/hle/kernel/k_thread_local_page.cpp index b4a1e3cdb..2c45b4232 100644 --- a/src/core/hle/kernel/k_thread_local_page.cpp +++ b/src/core/hle/kernel/k_thread_local_page.cpp @@ -25,9 +25,9 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) { // Map the address in. const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf); - R_TRY(m_owner->PageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, phys_addr, - KMemoryState::ThreadLocal, - KMemoryPermission::UserReadWrite)); + R_TRY(m_owner->GetPageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, phys_addr, + KMemoryState::ThreadLocal, + KMemoryPermission::UserReadWrite)); // We succeeded. page_buf_guard.Cancel(); @@ -37,11 +37,11 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) { Result KThreadLocalPage::Finalize() { // Get the physical address of the page. - const KPhysicalAddress phys_addr = m_owner->PageTable().GetPhysicalAddr(m_virt_addr); + const KPhysicalAddress phys_addr = m_owner->GetPageTable().GetPhysicalAddr(m_virt_addr); ASSERT(phys_addr); // Unmap the page. - R_TRY(m_owner->PageTable().UnmapPages(this->GetAddress(), 1, KMemoryState::ThreadLocal)); + R_TRY(m_owner->GetPageTable().UnmapPages(this->GetAddress(), 1, KMemoryState::ThreadLocal)); // Free the page. KPageBuffer::Free(*m_kernel, KPageBuffer::FromPhysicalAddress(m_kernel->System(), phys_addr)); diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f33600ca5..ebe7582c6 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -1089,15 +1089,15 @@ static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, KThread::Register(kernel, thread); return std::jthread( - [&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] { + [&kernel, thread, thread_name_{std::move(thread_name)}, func_{std::move(func)}] { // Set the thread name. - Common::SetCurrentThreadName(thread_name.c_str()); + Common::SetCurrentThreadName(thread_name_.c_str()); // Set the thread as current. kernel.RegisterHostThread(thread); // Run the callback. - func(); + func_(); // Close the thread. // This will free the process if it is the last reference. diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 2e0c36129..5ee869fa2 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -17,7 +17,9 @@ PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KSchedu // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. auto& kernel = system.Kernel(); m_arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( - system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), m_core_index); + system, kernel.IsMulticore(), + reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()), + m_core_index); #else #error Platform not supported yet. #endif @@ -31,7 +33,9 @@ void PhysicalCore::Initialize(bool is_64_bit) { if (!is_64_bit) { // We already initialized a 64-bit core, replace with a 32-bit one. m_arm_interface = std::make_unique<Core::ARM_Dynarmic_32>( - m_system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), m_core_index); + m_system, kernel.IsMulticore(), + reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()), + m_core_index); } #else #error Platform not supported yet. diff --git a/src/core/hle/kernel/svc/svc_cache.cpp b/src/core/hle/kernel/svc/svc_cache.cpp index 082942dab..c2c8be10f 100644 --- a/src/core/hle/kernel/svc/svc_cache.cpp +++ b/src/core/hle/kernel/svc/svc_cache.cpp @@ -42,7 +42,7 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Verify the region is within range. - auto& page_table = process->PageTable(); + auto& page_table = process->GetPageTable(); R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); // Perform the operation. diff --git a/src/core/hle/kernel/svc/svc_code_memory.cpp b/src/core/hle/kernel/svc/svc_code_memory.cpp index 687baff82..bae4cb0cd 100644 --- a/src/core/hle/kernel/svc/svc_code_memory.cpp +++ b/src/core/hle/kernel/svc/svc_code_memory.cpp @@ -48,7 +48,7 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t SCOPE_EXIT({ code_mem->Close(); }); // Verify that the region is in range. - R_UNLESS(GetCurrentProcess(system.Kernel()).PageTable().Contains(address, size), + R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size), ResultInvalidCurrentMemory); // Initialize the code memory. @@ -92,7 +92,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, case CodeMemoryOperation::Map: { // Check that the region is in range. R_UNLESS(GetCurrentProcess(system.Kernel()) - .PageTable() + .GetPageTable() .CanContain(address, size, KMemoryState::CodeOut), ResultInvalidMemoryRegion); @@ -105,7 +105,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, case CodeMemoryOperation::Unmap: { // Check that the region is in range. R_UNLESS(GetCurrentProcess(system.Kernel()) - .PageTable() + .GetPageTable() .CanContain(address, size, KMemoryState::CodeOut), ResultInvalidMemoryRegion); @@ -117,8 +117,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, } break; case CodeMemoryOperation::MapToOwner: { // Check that the region is in range. - R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size, - KMemoryState::GeneratedCode), + R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size, + KMemoryState::GeneratedCode), ResultInvalidMemoryRegion); // Check the memory permission. @@ -129,8 +129,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, } break; case CodeMemoryOperation::UnmapFromOwner: { // Check that the region is in range. - R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size, - KMemoryState::GeneratedCode), + R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size, + KMemoryState::GeneratedCode), ResultInvalidMemoryRegion); // Check the memory permission. diff --git a/src/core/hle/kernel/svc/svc_device_address_space.cpp b/src/core/hle/kernel/svc/svc_device_address_space.cpp index ec3143e67..42add9473 100644 --- a/src/core/hle/kernel/svc/svc_device_address_space.cpp +++ b/src/core/hle/kernel/svc/svc_device_address_space.cpp @@ -107,7 +107,7 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. - auto& page_table = process->PageTable(); + auto& page_table = process->GetPageTable(); R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory); // Map. @@ -148,7 +148,7 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. - auto& page_table = process->PageTable(); + auto& page_table = process->GetPageTable(); R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory); // Map. @@ -180,7 +180,7 @@ Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle p R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the process address is within range. - auto& page_table = process->PageTable(); + auto& page_table = process->GetPageTable(); R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory); R_RETURN(das->Unmap(std::addressof(page_table), process_address, size, device_address)); diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp index 445cdd87b..f99964028 100644 --- a/src/core/hle/kernel/svc/svc_info.cpp +++ b/src/core/hle/kernel/svc/svc_info.cpp @@ -54,35 +54,35 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_SUCCEED(); case InfoType::AliasRegionAddress: - *result = GetInteger(process->PageTable().GetAliasRegionStart()); + *result = GetInteger(process->GetPageTable().GetAliasRegionStart()); R_SUCCEED(); case InfoType::AliasRegionSize: - *result = process->PageTable().GetAliasRegionSize(); + *result = process->GetPageTable().GetAliasRegionSize(); R_SUCCEED(); case InfoType::HeapRegionAddress: - *result = GetInteger(process->PageTable().GetHeapRegionStart()); + *result = GetInteger(process->GetPageTable().GetHeapRegionStart()); R_SUCCEED(); case InfoType::HeapRegionSize: - *result = process->PageTable().GetHeapRegionSize(); + *result = process->GetPageTable().GetHeapRegionSize(); R_SUCCEED(); case InfoType::AslrRegionAddress: - *result = GetInteger(process->PageTable().GetAliasCodeRegionStart()); + *result = GetInteger(process->GetPageTable().GetAliasCodeRegionStart()); R_SUCCEED(); case InfoType::AslrRegionSize: - *result = process->PageTable().GetAliasCodeRegionSize(); + *result = process->GetPageTable().GetAliasCodeRegionSize(); R_SUCCEED(); case InfoType::StackRegionAddress: - *result = GetInteger(process->PageTable().GetStackRegionStart()); + *result = GetInteger(process->GetPageTable().GetStackRegionStart()); R_SUCCEED(); case InfoType::StackRegionSize: - *result = process->PageTable().GetStackRegionSize(); + *result = process->GetPageTable().GetStackRegionSize(); R_SUCCEED(); case InfoType::TotalMemorySize: diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp index bb94f6934..373ae7c8d 100644 --- a/src/core/hle/kernel/svc/svc_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_ipc.cpp @@ -8,6 +8,7 @@ #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/svc.h" +#include "core/hle/kernel/svc_results.h" namespace Kernel::Svc { @@ -49,14 +50,10 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad // Copy user handles. if (num_handles > 0) { - // Ensure we can try to get the handles. - R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange( - handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)), - ResultInvalidPointer); - // Get the handles. - GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), - sizeof(Handle) * num_handles); + R_UNLESS(GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), + sizeof(Handle) * num_handles), + ResultInvalidPointer); // Convert the handles to objects. R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( diff --git a/src/core/hle/kernel/svc/svc_memory.cpp b/src/core/hle/kernel/svc/svc_memory.cpp index 5dcb7f045..2cab74127 100644 --- a/src/core/hle/kernel/svc/svc_memory.cpp +++ b/src/core/hle/kernel/svc/svc_memory.cpp @@ -63,36 +63,13 @@ Result MapUnmapMemorySanityChecks(const KPageTable& manager, u64 dst_addr, u64 s R_THROW(ResultInvalidCurrentMemory); } - if (!manager.IsInsideAddressSpace(src_addr, size)) { + if (!manager.Contains(src_addr, size)) { LOG_ERROR(Kernel_SVC, "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", src_addr, size); R_THROW(ResultInvalidCurrentMemory); } - if (manager.IsOutsideStackRegion(dst_addr, size)) { - LOG_ERROR(Kernel_SVC, - "Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}", - dst_addr, size); - R_THROW(ResultInvalidMemoryRegion); - } - - if (manager.IsInsideHeapRegion(dst_addr, size)) { - LOG_ERROR(Kernel_SVC, - "Destination does not fit within the heap region, addr=0x{:016X}, " - "size=0x{:016X}", - dst_addr, size); - R_THROW(ResultInvalidMemoryRegion); - } - - if (manager.IsInsideAliasRegion(dst_addr, size)) { - LOG_ERROR(Kernel_SVC, - "Destination does not fit within the map region, addr=0x{:016X}, " - "size=0x{:016X}", - dst_addr, size); - R_THROW(ResultInvalidMemoryRegion); - } - R_SUCCEED(); } @@ -112,7 +89,7 @@ Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPe R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission); // Validate that the region is in range for the current process. - auto& page_table = GetCurrentProcess(system.Kernel()).PageTable(); + auto& page_table = GetCurrentProcess(system.Kernel()).GetPageTable(); R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); // Set the memory attribute. @@ -136,7 +113,7 @@ Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask, R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination); // Validate that the region is in range for the current process. - auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()}; + auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()}; R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); // Set the memory attribute. @@ -148,7 +125,7 @@ Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) { LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, src_addr, size); - auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()}; + auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()}; if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)}; result.IsError()) { @@ -163,7 +140,7 @@ Result UnmapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) { LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, src_addr, size); - auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()}; + auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()}; if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)}; result.IsError()) { diff --git a/src/core/hle/kernel/svc/svc_physical_memory.cpp b/src/core/hle/kernel/svc/svc_physical_memory.cpp index c2fbfb59a..d3545f232 100644 --- a/src/core/hle/kernel/svc/svc_physical_memory.cpp +++ b/src/core/hle/kernel/svc/svc_physical_memory.cpp @@ -16,7 +16,7 @@ Result SetHeapSize(Core::System& system, u64* out_address, u64 size) { R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize); // Set the heap size. - R_RETURN(GetCurrentProcess(system.Kernel()).PageTable().SetHeapSize(out_address, size)); + R_RETURN(GetCurrentProcess(system.Kernel()).GetPageTable().SetHeapSize(out_address, size)); } /// Maps memory at a desired address @@ -44,21 +44,21 @@ Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) { } KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())}; - auto& page_table{current_process->PageTable()}; + auto& page_table{current_process->GetPageTable()}; if (current_process->GetSystemResourceSize() == 0) { LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); R_THROW(ResultInvalidState); } - if (!page_table.IsInsideAddressSpace(addr, size)) { + if (!page_table.Contains(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, size); R_THROW(ResultInvalidMemoryRegion); } - if (page_table.IsOutsideAliasRegion(addr, size)) { + if (!page_table.IsInAliasRegion(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, size); @@ -93,21 +93,21 @@ Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) { } KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())}; - auto& page_table{current_process->PageTable()}; + auto& page_table{current_process->GetPageTable()}; if (current_process->GetSystemResourceSize() == 0) { LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); R_THROW(ResultInvalidState); } - if (!page_table.IsInsideAddressSpace(addr, size)) { + if (!page_table.Contains(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, size); R_THROW(ResultInvalidMemoryRegion); } - if (page_table.IsOutsideAliasRegion(addr, size)) { + if (!page_table.IsInAliasRegion(addr, size)) { LOG_ERROR(Kernel_SVC, "Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr, size); diff --git a/src/core/hle/kernel/svc/svc_process.cpp b/src/core/hle/kernel/svc/svc_process.cpp index 619ed16a3..caa8bee9a 100644 --- a/src/core/hle/kernel/svc/svc_process.cpp +++ b/src/core/hle/kernel/svc/svc_process.cpp @@ -66,8 +66,8 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc auto& kernel = system.Kernel(); const auto total_copy_size = out_process_ids_size * sizeof(u64); - if (out_process_ids_size > 0 && !GetCurrentProcess(kernel).PageTable().IsInsideAddressSpace( - out_process_ids, total_copy_size)) { + if (out_process_ids_size > 0 && + !GetCurrentProcess(kernel).GetPageTable().Contains(out_process_ids, total_copy_size)) { LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", out_process_ids, out_process_ids + total_copy_size); R_THROW(ResultInvalidCurrentMemory); diff --git a/src/core/hle/kernel/svc/svc_process_memory.cpp b/src/core/hle/kernel/svc/svc_process_memory.cpp index aee0f2f36..07cd48175 100644 --- a/src/core/hle/kernel/svc/svc_process_memory.cpp +++ b/src/core/hle/kernel/svc/svc_process_memory.cpp @@ -49,7 +49,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u R_UNLESS(process.IsNotNull(), ResultInvalidHandle); // Validate that the address is in range. - auto& page_table = process->PageTable(); + auto& page_table = process->GetPageTable(); R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); // Set the memory permission. @@ -77,8 +77,8 @@ Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_ha R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); // Get the page tables. - auto& dst_pt = dst_process->PageTable(); - auto& src_pt = src_process->PageTable(); + auto& dst_pt = dst_process->GetPageTable(); + auto& src_pt = src_process->GetPageTable(); // Validate that the mapping is in range. R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory); @@ -118,8 +118,8 @@ Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_ R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle); // Get the page tables. - auto& dst_pt = dst_process->PageTable(); - auto& src_pt = src_process->PageTable(); + auto& dst_pt = dst_process->GetPageTable(); + auto& src_pt = src_process->GetPageTable(); // Validate that the mapping is in range. R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory); @@ -178,8 +178,8 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst R_THROW(ResultInvalidHandle); } - auto& page_table = process->PageTable(); - if (!page_table.IsInsideAddressSpace(src_address, size)) { + auto& page_table = process->GetPageTable(); + if (!page_table.Contains(src_address, size)) { LOG_ERROR(Kernel_SVC, "Source address range is not within the address space (src_address=0x{:016X}, " "size=0x{:016X}).", @@ -187,14 +187,6 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst R_THROW(ResultInvalidCurrentMemory); } - if (!page_table.IsInsideASLRRegion(dst_address, size)) { - LOG_ERROR(Kernel_SVC, - "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " - "size=0x{:016X}).", - dst_address, size); - R_THROW(ResultInvalidMemoryRegion); - } - R_RETURN(page_table.MapCodeMemory(dst_address, src_address, size)); } @@ -246,8 +238,8 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d R_THROW(ResultInvalidHandle); } - auto& page_table = process->PageTable(); - if (!page_table.IsInsideAddressSpace(src_address, size)) { + auto& page_table = process->GetPageTable(); + if (!page_table.Contains(src_address, size)) { LOG_ERROR(Kernel_SVC, "Source address range is not within the address space (src_address=0x{:016X}, " "size=0x{:016X}).", @@ -255,14 +247,6 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d R_THROW(ResultInvalidCurrentMemory); } - if (!page_table.IsInsideASLRRegion(dst_address, size)) { - LOG_ERROR(Kernel_SVC, - "Destination address range is not within the ASLR region (dst_address=0x{:016X}, " - "size=0x{:016X}).", - dst_address, size); - R_THROW(ResultInvalidMemoryRegion); - } - R_RETURN(page_table.UnmapCodeMemory(dst_address, src_address, size, KPageTable::ICacheInvalidationStrategy::InvalidateAll)); } diff --git a/src/core/hle/kernel/svc/svc_query_memory.cpp b/src/core/hle/kernel/svc/svc_query_memory.cpp index 4d9fcd25f..51af06e97 100644 --- a/src/core/hle/kernel/svc/svc_query_memory.cpp +++ b/src/core/hle/kernel/svc/svc_query_memory.cpp @@ -31,7 +31,7 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn } auto& current_memory{GetCurrentMemory(system.Kernel())}; - const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()}; + const auto memory_info{process->GetPageTable().QueryInfo(address).GetSvcMemoryInfo()}; current_memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info)); diff --git a/src/core/hle/kernel/svc/svc_shared_memory.cpp b/src/core/hle/kernel/svc/svc_shared_memory.cpp index a698596aa..012b1ae2b 100644 --- a/src/core/hle/kernel/svc/svc_shared_memory.cpp +++ b/src/core/hle/kernel/svc/svc_shared_memory.cpp @@ -43,7 +43,7 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u // Get the current process. auto& process = GetCurrentProcess(system.Kernel()); - auto& page_table = process.PageTable(); + auto& page_table = process.GetPageTable(); // Get the shared memory. KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); @@ -73,7 +73,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, // Get the current process. auto& process = GetCurrentProcess(system.Kernel()); - auto& page_table = process.PageTable(); + auto& page_table = process.GetPageTable(); // Get the shared memory. KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle); diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index f02d03f30..366e8ed4a 100644 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp @@ -7,6 +7,7 @@ #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/svc.h" +#include "core/hle/kernel/svc_results.h" namespace Kernel::Svc { @@ -64,14 +65,10 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha // Copy user handles. if (num_handles > 0) { - // Ensure we can try to get the handles. - R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange( - user_handles, static_cast<u64>(sizeof(Handle) * num_handles)), - ResultInvalidPointer); - // Get the handles. - GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(), - sizeof(Handle) * num_handles); + R_UNLESS(GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(), + sizeof(Handle) * num_handles), + ResultInvalidPointer); // Convert the handles to objects. R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>( diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index 36b94e6bf..92bcea72b 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -236,7 +236,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_ const auto total_copy_size = out_thread_ids_size * sizeof(u64); if (out_thread_ids_size > 0 && - !current_process->PageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) { + !current_process->GetPageTable().Contains(out_thread_ids, total_copy_size)) { LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}", out_thread_ids, out_thread_ids + total_copy_size); R_THROW(ResultInvalidCurrentMemory); diff --git a/src/core/hle/kernel/svc/svc_transfer_memory.cpp b/src/core/hle/kernel/svc/svc_transfer_memory.cpp index 82d469a37..7d94e7f09 100644 --- a/src/core/hle/kernel/svc/svc_transfer_memory.cpp +++ b/src/core/hle/kernel/svc/svc_transfer_memory.cpp @@ -55,7 +55,7 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64 SCOPE_EXIT({ trmem->Close(); }); // Ensure that the region is in range. - R_UNLESS(process.PageTable().Contains(address, size), ResultInvalidCurrentMemory); + R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory); // Initialize the transfer memory. R_TRY(trmem->Initialize(address, size, map_perm)); diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 6c29cb613..2632cd3ef 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -496,8 +496,9 @@ public: void LoadIdTokenCache(HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); + rb.Push(0); } protected: diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a2375508a..4f400d341 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -506,8 +506,8 @@ void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) { void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; idle_time_detection_extension = rp.Pop<u32>(); - LOG_WARNING(Service_AM, "(STUBBED) called idle_time_detection_extension={}", - idle_time_detection_extension); + LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}", + idle_time_detection_extension); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/glue/ectx.cpp b/src/core/hle/service/glue/ectx.cpp index 1bd9314ae..6f71b62f3 100644 --- a/src/core/hle/service/glue/ectx.cpp +++ b/src/core/hle/service/glue/ectx.cpp @@ -2,13 +2,48 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/hle/service/glue/ectx.h" +#include "core/hle/service/ipc_helpers.h" namespace Service::Glue { +// This is nn::err::context::IContextRegistrar +class IContextRegistrar : public ServiceFramework<IContextRegistrar> { +public: + IContextRegistrar(Core::System& system_) : ServiceFramework{system_, "IContextRegistrar"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IContextRegistrar::Complete, "Complete"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + + ~IContextRegistrar() override = default; + +private: + void Complete(HLERequestContext& ctx) { + struct InputParameters { + u32 unk; + }; + struct OutputParameters { + u32 unk; + }; + + IPC::RequestParser rp{ctx}; + [[maybe_unused]] auto input = rp.PopRaw<InputParameters>(); + [[maybe_unused]] auto value = ctx.ReadBuffer(); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); + } +}; + ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "CreateContextRegistrar"}, + {0, &ECTX_AW::CreateContextRegistrar, "CreateContextRegistrar"}, {1, nullptr, "CommitContext"}, }; // clang-format on @@ -18,4 +53,10 @@ ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} { ECTX_AW::~ECTX_AW() = default; +void ECTX_AW::CreateContextRegistrar(HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<IContextRegistrar>(std::make_shared<IContextRegistrar>(system)); +} + } // namespace Service::Glue diff --git a/src/core/hle/service/glue/ectx.h b/src/core/hle/service/glue/ectx.h index a608de053..ffa74d8d3 100644 --- a/src/core/hle/service/glue/ectx.h +++ b/src/core/hle/service/glue/ectx.h @@ -15,6 +15,9 @@ class ECTX_AW final : public ServiceFramework<ECTX_AW> { public: explicit ECTX_AW(Core::System& system_); ~ECTX_AW() override; + +private: + void CreateContextRegistrar(HLERequestContext& ctx); }; } // namespace Service::Glue diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index c42489ff9..055c0a2db 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -318,15 +318,15 @@ public: return false; } - if (!page_table.IsInsideAddressSpace(out_addr, size)) { + if (!page_table.Contains(out_addr, size)) { return false; } - if (page_table.IsInsideHeapRegion(out_addr, size)) { + if (page_table.IsInHeapRegion(out_addr, size)) { return false; } - if (page_table.IsInsideAliasRegion(out_addr, size)) { + if (page_table.IsInAliasRegion(out_addr, size)) { return false; } @@ -358,7 +358,7 @@ public: } ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) { - auto& page_table{process->PageTable()}; + auto& page_table{process->GetPageTable()}; VAddr addr{}; for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { @@ -382,7 +382,7 @@ public: ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size, VAddr bss_addr, std::size_t bss_size, std::size_t size) { for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { - auto& page_table{process->PageTable()}; + auto& page_table{process->GetPageTable()}; VAddr addr{}; CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size)); @@ -437,12 +437,12 @@ public: CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start, nro_header.segment_headers[DATA_INDEX].memory_size); - CASCADE_CODE(process->PageTable().SetProcessMemoryPermission( + CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission( text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute)); - CASCADE_CODE(process->PageTable().SetProcessMemoryPermission( + CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission( ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read)); - return process->PageTable().SetProcessMemoryPermission( + return process->GetPageTable().SetProcessMemoryPermission( data_start, bss_end_addr - data_start, Kernel::Svc::MemoryPermission::ReadWrite); } @@ -571,7 +571,7 @@ public: Result UnmapNro(const NROInfo& info) { // Each region must be unmapped separately to validate memory state - auto& page_table{system.ApplicationProcess()->PageTable()}; + auto& page_table{system.ApplicationProcess()->GetPageTable()}; if (info.bss_size != 0) { CASCADE_CODE(page_table.UnmapCodeMemory( @@ -643,7 +643,7 @@ public: initialized = true; current_map_addr = - GetInteger(system.ApplicationProcess()->PageTable().GetAliasCodeRegionStart()); + GetInteger(system.ApplicationProcess()->GetPageTable().GetAliasCodeRegionStart()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.cpp b/src/core/hle/service/nfc/common/amiibo_crypto.cpp index bc232c334..9556e9193 100644 --- a/src/core/hle/service/nfc/common/amiibo_crypto.cpp +++ b/src/core/hle/service/nfc/common/amiibo_crypto.cpp @@ -180,7 +180,7 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed } void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key, - const std::vector<u8>& seed) { + std::span<const u8> seed) { // Initialize context ctx.used = false; ctx.counter = 0; diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.h b/src/core/hle/service/nfc/common/amiibo_crypto.h index 6a3e0841e..2cc0e4d51 100644 --- a/src/core/hle/service/nfc/common/amiibo_crypto.h +++ b/src/core/hle/service/nfc/common/amiibo_crypto.h @@ -75,7 +75,7 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed // Initializes mbedtls context void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key, - const std::vector<u8>& seed); + std::span<const u8> seed); // Feeds data to mbedtls context to generate the derived key void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output); diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp index 2d633b03f..49446bc42 100644 --- a/src/core/hle/service/nfc/common/device.cpp +++ b/src/core/hle/service/nfc/common/device.cpp @@ -34,8 +34,6 @@ #include "core/hle/service/nfc/mifare_result.h" #include "core/hle/service/nfc/nfc_result.h" #include "core/hle/service/time/time_manager.h" -#include "core/hle/service/time/time_zone_content_manager.h" -#include "core/hle/service/time/time_zone_types.h" namespace Service::NFC { NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_, @@ -1486,6 +1484,7 @@ DeviceState NfcDevice::GetCurrentState() const { } Result NfcDevice::GetNpadId(Core::HID::NpadIdType& out_npad_id) const { + // TODO: This should get the npad id from nn::hid::system::GetXcdHandleForNpadWithNfc out_npad_id = npad_id; return ResultSuccess; } diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp index 562f3a28e..a71d26157 100644 --- a/src/core/hle/service/nfc/common/device_manager.cpp +++ b/src/core/hle/service/nfc/common/device_manager.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include <algorithm> + #include "common/logging/log.h" #include "core/core.h" #include "core/hid/hid_types.h" @@ -10,6 +12,7 @@ #include "core/hle/service/nfc/common/device_manager.h" #include "core/hle/service/nfc/nfc_result.h" #include "core/hle/service/time/clock_types.h" +#include "core/hle/service/time/time_manager.h" namespace Service::NFC { @@ -51,22 +54,53 @@ Result DeviceManager::Finalize() { return ResultSuccess; } -Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, - std::size_t max_allowed_devices) const { +Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices, + bool skip_fatal_errors) const { + std::scoped_lock lock{mutex}; + if (max_allowed_devices < 1) { + return ResultInvalidArgument; + } + + Result result = IsNfcParameterSet(); + if (result.IsError()) { + return result; + } + + result = IsNfcEnabled(); + if (result.IsError()) { + return result; + } + + result = IsNfcInitialized(); + if (result.IsError()) { + return result; + } + for (auto& device : devices) { if (nfp_devices.size() >= max_allowed_devices) { continue; } - if (device->GetCurrentState() != DeviceState::Unavailable) { - nfp_devices.push_back(device->GetHandle()); + if (skip_fatal_errors) { + constexpr u64 MinimumRecoveryTime = 60; + auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()}; + const u64 elapsed_time = standard_steady_clock.GetCurrentTimePoint(system).time_point - + time_since_last_error; + + if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) { + continue; + } } + if (device->GetCurrentState() == DeviceState::Unavailable) { + continue; + } + nfp_devices.push_back(device->GetHandle()); } if (nfp_devices.empty()) { return ResultDeviceNotFound; } - return ResultSuccess; + return result; } DeviceState DeviceManager::GetDeviceState(u64 device_handle) const { @@ -79,10 +113,10 @@ DeviceState DeviceManager::GetDeviceState(u64 device_handle) const { return device->GetCurrentState(); } - return DeviceState::Unavailable; + return DeviceState::Finalized; } -Result DeviceManager::GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const { +Result DeviceManager::GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -128,7 +162,7 @@ Result DeviceManager::StopDetection(u64 device_handle) { return result; } -Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const { +Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -142,24 +176,46 @@ Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const { return result; } -Kernel::KReadableEvent& DeviceManager::AttachActivateEvent(u64 device_handle) const { - std::scoped_lock lock{mutex}; - +Result DeviceManager::AttachActivateEvent(Kernel::KReadableEvent** out_event, + u64 device_handle) const { + std::vector<u64> nfp_devices; std::shared_ptr<NfcDevice> device = nullptr; - GetDeviceFromHandle(device_handle, device, false); + Result result = ListDevices(nfp_devices, 9, false); - // TODO: Return proper error code on failure - return device->GetActivateEvent(); -} + if (result.IsSuccess()) { + result = CheckHandleOnList(device_handle, nfp_devices); + } -Kernel::KReadableEvent& DeviceManager::AttachDeactivateEvent(u64 device_handle) const { - std::scoped_lock lock{mutex}; + if (result.IsSuccess()) { + result = GetDeviceFromHandle(device_handle, device, false); + } + + if (result.IsSuccess()) { + *out_event = &device->GetActivateEvent(); + } + + return result; +} +Result DeviceManager::AttachDeactivateEvent(Kernel::KReadableEvent** out_event, + u64 device_handle) const { + std::vector<u64> nfp_devices; std::shared_ptr<NfcDevice> device = nullptr; - GetDeviceFromHandle(device_handle, device, false); + Result result = ListDevices(nfp_devices, 9, false); - // TODO: Return proper error code on failure - return device->GetDeactivateEvent(); + if (result.IsSuccess()) { + result = CheckHandleOnList(device_handle, nfp_devices); + } + + if (result.IsSuccess()) { + result = GetDeviceFromHandle(device_handle, device, false); + } + + if (result.IsSuccess()) { + *out_event = &device->GetDeactivateEvent(); + } + + return result; } Result DeviceManager::ReadMifare(u64 device_handle, @@ -253,7 +309,7 @@ Result DeviceManager::OpenApplicationArea(u64 device_handle, u32 access_id) { return result; } -Result DeviceManager::GetApplicationArea(u64 device_handle, std::span<u8> data) const { +Result DeviceManager::GetApplicationArea(u64 device_handle, std::span<u8> data) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -324,7 +380,7 @@ Result DeviceManager::CreateApplicationArea(u64 device_handle, u32 access_id, return result; } -Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const { +Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -338,7 +394,7 @@ Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& regi return result; } -Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const { +Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -352,7 +408,7 @@ Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_i return result; } -Result DeviceManager::GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const { +Result DeviceManager::GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -399,7 +455,7 @@ Result DeviceManager::Format(u64 device_handle) { return result; } -Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const { +Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -414,7 +470,7 @@ Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info } Result DeviceManager::GetRegisterInfoPrivate(u64 device_handle, - NFP::RegisterInfoPrivate& register_info) const { + NFP::RegisterInfoPrivate& register_info) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -471,7 +527,7 @@ Result DeviceManager::DeleteApplicationArea(u64 device_handle) { return result; } -Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_application_area) const { +Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_application_area) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -485,7 +541,7 @@ Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_applica return result; } -Result DeviceManager::GetAll(u64 device_handle, NFP::NfpData& nfp_data) const { +Result DeviceManager::GetAll(u64 device_handle, NFP::NfpData& nfp_data) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -541,7 +597,7 @@ Result DeviceManager::BreakTag(u64 device_handle, NFP::BreakType break_type) { return result; } -Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) const { +Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) { std::scoped_lock lock{mutex}; std::shared_ptr<NfcDevice> device = nullptr; @@ -593,6 +649,19 @@ Result DeviceManager::WriteNtf(u64 device_handle, NFP::WriteType, std::span<cons return result; } +Result DeviceManager::CheckHandleOnList(u64 device_handle, + const std::span<const u64> device_list) const { + if (device_list.size() < 1) { + return ResultDeviceNotFound; + } + + if (std::find(device_list.begin(), device_list.end(), device_handle) != device_list.end()) { + return ResultSuccess; + } + + return ResultDeviceNotFound; +} + Result DeviceManager::GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& nfc_device, bool check_state) const { if (check_state) { @@ -647,7 +716,7 @@ Result DeviceManager::GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& de } Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device, - Result operation_result) const { + Result operation_result) { if (operation_result.IsSuccess()) { return operation_result; } @@ -669,6 +738,12 @@ Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device, return device_state; } + if (operation_result == ResultUnknown112 || operation_result == ResultUnknown114 || + operation_result == ResultUnknown115) { + auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()}; + time_since_last_error = standard_steady_clock.GetCurrentTimePoint(system).time_point; + } + return operation_result; } diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h index c61ba0cf3..c9f038e32 100644 --- a/src/core/hle/service/nfc/common/device_manager.h +++ b/src/core/hle/service/nfc/common/device_manager.h @@ -27,15 +27,16 @@ public: // Nfc device manager Result Initialize(); Result Finalize(); - Result ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices) const; + Result ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices, + bool skip_fatal_errors) const; DeviceState GetDeviceState(u64 device_handle) const; - Result GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const; + Result GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id); Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const; Result StartDetection(u64 device_handle, NfcProtocol tag_protocol); Result StopDetection(u64 device_handle); - Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info) const; - Kernel::KReadableEvent& AttachActivateEvent(u64 device_handle) const; - Kernel::KReadableEvent& AttachDeactivateEvent(u64 device_handle) const; + Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info); + Result AttachActivateEvent(Kernel::KReadableEvent** event, u64 device_handle) const; + Result AttachDeactivateEvent(Kernel::KReadableEvent** event, u64 device_handle) const; Result ReadMifare(u64 device_handle, const std::span<const MifareReadBlockParameter> read_parameters, std::span<MifareReadBlockData> read_data); @@ -48,28 +49,28 @@ public: Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target); Result Unmount(u64 device_handle); Result OpenApplicationArea(u64 device_handle, u32 access_id); - Result GetApplicationArea(u64 device_handle, std::span<u8> data) const; + Result GetApplicationArea(u64 device_handle, std::span<u8> data); Result SetApplicationArea(u64 device_handle, std::span<const u8> data); Result Flush(u64 device_handle); Result Restore(u64 device_handle); Result CreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data); - Result GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const; - Result GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const; - Result GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const; + Result GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info); + Result GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info); + Result GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info); u32 GetApplicationAreaSize() const; Result RecreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data); Result Format(u64 device_handle); - Result GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const; - Result GetRegisterInfoPrivate(u64 device_handle, NFP::RegisterInfoPrivate& register_info) const; + Result GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info); + Result GetRegisterInfoPrivate(u64 device_handle, NFP::RegisterInfoPrivate& register_info); Result SetRegisterInfoPrivate(u64 device_handle, const NFP::RegisterInfoPrivate& register_info); Result DeleteRegisterInfo(u64 device_handle); Result DeleteApplicationArea(u64 device_handle); - Result ExistsApplicationArea(u64 device_handle, bool& has_application_area) const; - Result GetAll(u64 device_handle, NFP::NfpData& nfp_data) const; + Result ExistsApplicationArea(u64 device_handle, bool& has_application_area); + Result GetAll(u64 device_handle, NFP::NfpData& nfp_data); Result SetAll(u64 device_handle, const NFP::NfpData& nfp_data); Result FlushDebug(u64 device_handle); Result BreakTag(u64 device_handle, NFP::BreakType break_type); - Result ReadBackupData(u64 device_handle, std::span<u8> data) const; + Result ReadBackupData(u64 device_handle, std::span<u8> data); Result WriteBackupData(u64 device_handle, std::span<const u8> data); Result WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data); @@ -78,17 +79,20 @@ private: Result IsNfcParameterSet() const; Result IsNfcInitialized() const; + Result CheckHandleOnList(u64 device_handle, std::span<const u64> device_list) const; + Result GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& device, bool check_state) const; Result GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const; - Result VerifyDeviceResult(std::shared_ptr<NfcDevice> device, Result operation_result) const; + Result VerifyDeviceResult(std::shared_ptr<NfcDevice> device, Result operation_result); Result CheckDeviceState(std::shared_ptr<NfcDevice> device) const; std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle); const std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle) const; bool is_initialized = false; + u64 time_since_last_error = 0; mutable std::mutex mutex; std::array<std::shared_ptr<NfcDevice>, 10> devices{}; diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp index e7ca7582e..179c7ba2c 100644 --- a/src/core/hle/service/nfc/nfc_interface.cpp +++ b/src/core/hle/service/nfc/nfc_interface.cpp @@ -79,7 +79,7 @@ void NfcInterface::ListDevices(HLERequestContext& ctx) { const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); LOG_DEBUG(Service_NFC, "called"); - auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices); + auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices, true); result = TranslateResultToServiceError(result); if (result.IsError()) { @@ -190,9 +190,13 @@ void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) { const auto device_handle{rp.Pop<u64>()}; LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + Kernel::KReadableEvent* out_event = nullptr; + auto result = GetManager()->AttachActivateEvent(&out_event, device_handle); + result = TranslateResultToServiceError(result); + IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(GetManager()->AttachActivateEvent(device_handle)); + rb.Push(result); + rb.PushCopyObjects(out_event); } void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) { @@ -200,9 +204,13 @@ void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) { const auto device_handle{rp.Pop<u64>()}; LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); + Kernel::KReadableEvent* out_event = nullptr; + auto result = GetManager()->AttachDeactivateEvent(&out_event, device_handle); + result = TranslateResultToServiceError(result); + IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(GetManager()->AttachDeactivateEvent(device_handle)); + rb.Push(result); + rb.PushCopyObjects(out_event); } void NfcInterface::ReadMifare(HLERequestContext& ctx) { diff --git a/src/core/hle/service/nfc/nfc_result.h b/src/core/hle/service/nfc/nfc_result.h index 715c0e80c..464b5fd69 100644 --- a/src/core/hle/service/nfc/nfc_result.h +++ b/src/core/hle/service/nfc/nfc_result.h @@ -17,7 +17,10 @@ constexpr Result ResultNfcNotInitialized(ErrorModule::NFC, 77); constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80); constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFC, 88); constexpr Result ResultTagRemoved(ErrorModule::NFC, 97); +constexpr Result ResultUnknown112(ErrorModule::NFC, 112); constexpr Result ResultUnableToAccessBackupFile(ErrorModule::NFC, 113); +constexpr Result ResultUnknown114(ErrorModule::NFC, 114); +constexpr Result ResultUnknown115(ErrorModule::NFC, 115); constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFC, 120); constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFC, 128); constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFC, 136); diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index e7f7e273b..968eaa175 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -128,7 +128,7 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) { } bool is_out_io{}; ASSERT(system.ApplicationProcess() - ->PageTable() + ->GetPageTable() .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address, handle_description->size, Kernel::KMemoryPermission::None, true, false) @@ -255,7 +255,7 @@ NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) { if (auto freeInfo{file.FreeHandle(params.handle, false)}) { if (freeInfo->can_unlock) { ASSERT(system.ApplicationProcess() - ->PageTable() + ->GetPageTable() .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size) .IsSuccess()); } diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp index e63b0a357..11f8efbac 100644 --- a/src/core/hle/service/sockets/bsd.cpp +++ b/src/core/hle/service/sockets/bsd.cpp @@ -559,7 +559,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con const std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd]; if (!descriptor) { - LOG_ERROR(Service, "File descriptor handle={} is not allocated", pollfd.fd); + LOG_TRACE(Service, "File descriptor handle={} is not allocated", pollfd.fd); pollfd.revents = PollEvents::Nval; return {0, Errno::SUCCESS}; } diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp index 0dfb0f166..5dfcaabb1 100644 --- a/src/core/hle/service/sockets/nsd.cpp +++ b/src/core/hle/service/sockets/nsd.cpp @@ -10,12 +10,21 @@ namespace Service::Sockets { constexpr Result ResultOverflow{ErrorModule::NSD, 6}; +// This is nn::oe::ServerEnvironmentType +enum class ServerEnvironmentType : u8 { + Dd, + Lp, + Sd, + Sp, + Dp, +}; + NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { // clang-format off static const FunctionInfo functions[] = { {5, nullptr, "GetSettingUrl"}, {10, nullptr, "GetSettingName"}, - {11, nullptr, "GetEnvironmentIdentifier"}, + {11, &NSD::GetEnvironmentIdentifier, "GetEnvironmentIdentifier"}, {12, nullptr, "GetDeviceId"}, {13, nullptr, "DeleteSettings"}, {14, nullptr, "ImportSettings"}, @@ -36,7 +45,7 @@ NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, na {62, nullptr, "DeleteSaveDataOfFsForTest"}, {63, nullptr, "IsChangeEnvironmentIdentifierDisabled"}, {64, nullptr, "SetWithoutDomainExchangeFqdns"}, - {100, nullptr, "GetApplicationServerEnvironmentType"}, + {100, &NSD::GetApplicationServerEnvironmentType, "GetApplicationServerEnvironmentType"}, {101, nullptr, "SetApplicationServerEnvironmentType"}, {102, nullptr, "DeleteApplicationServerEnvironmentType"}, }; @@ -94,6 +103,20 @@ void NSD::ResolveEx(HLERequestContext& ctx) { rb.Push(ResultSuccess); } +void NSD::GetEnvironmentIdentifier(HLERequestContext& ctx) { + const std::string environment_identifier = "lp1"; + ctx.WriteBuffer(environment_identifier); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void NSD::GetApplicationServerEnvironmentType(HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast<u32>(ServerEnvironmentType::Lp)); +} + NSD::~NSD() = default; } // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/nsd.h b/src/core/hle/service/sockets/nsd.h index a7379a8a9..b0cfec507 100644 --- a/src/core/hle/service/sockets/nsd.h +++ b/src/core/hle/service/sockets/nsd.h @@ -19,6 +19,8 @@ public: private: void Resolve(HLERequestContext& ctx); void ResolveEx(HLERequestContext& ctx); + void GetEnvironmentIdentifier(HLERequestContext& ctx); + void GetApplicationServerEnvironmentType(HLERequestContext& ctx); }; } // namespace Service::Sockets diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp index 84cc79de8..22e4a6f49 100644 --- a/src/core/hle/service/sockets/sfdnsres.cpp +++ b/src/core/hle/service/sockets/sfdnsres.cpp @@ -24,7 +24,7 @@ SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres" {2, &SFDNSRES::GetHostByNameRequest, "GetHostByNameRequest"}, {3, nullptr, "GetHostByAddrRequest"}, {4, nullptr, "GetHostStringErrorRequest"}, - {5, nullptr, "GetGaiStringErrorRequest"}, + {5, &SFDNSRES::GetGaiStringErrorRequest, "GetGaiStringErrorRequest"}, {6, &SFDNSRES::GetAddrInfoRequest, "GetAddrInfoRequest"}, {7, nullptr, "GetNameInfoRequest"}, {8, nullptr, "RequestCancelHandleRequest"}, @@ -300,6 +300,20 @@ void SFDNSRES::GetAddrInfoRequest(HLERequestContext& ctx) { }); } +void SFDNSRES::GetGaiStringErrorRequest(HLERequestContext& ctx) { + struct InputParameters { + GetAddrInfoError gai_errno; + }; + IPC::RequestParser rp{ctx}; + auto input = rp.PopRaw<InputParameters>(); + + const std::string result = Translate(input.gai_errno); + ctx.WriteBuffer(result); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) { // Additional options are ignored auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx); diff --git a/src/core/hle/service/sockets/sfdnsres.h b/src/core/hle/service/sockets/sfdnsres.h index d99a9d560..282ef9071 100644 --- a/src/core/hle/service/sockets/sfdnsres.h +++ b/src/core/hle/service/sockets/sfdnsres.h @@ -18,6 +18,7 @@ public: private: void GetHostByNameRequest(HLERequestContext& ctx); + void GetGaiStringErrorRequest(HLERequestContext& ctx); void GetHostByNameRequestWithOptions(HLERequestContext& ctx); void GetAddrInfoRequest(HLERequestContext& ctx); void GetAddrInfoRequestWithOptions(HLERequestContext& ctx); diff --git a/src/core/hle/service/sockets/sockets_translate.cpp b/src/core/hle/service/sockets/sockets_translate.cpp index 2f9a0e39c..c1187209f 100644 --- a/src/core/hle/service/sockets/sockets_translate.cpp +++ b/src/core/hle/service/sockets/sockets_translate.cpp @@ -81,6 +81,44 @@ GetAddrInfoError Translate(Network::GetAddrInfoError error) { } } +const char* Translate(GetAddrInfoError error) { + // https://android.googlesource.com/platform/bionic/+/085543106/libc/dns/net/getaddrinfo.c#254 + switch (error) { + case GetAddrInfoError::SUCCESS: + return "Success"; + case GetAddrInfoError::ADDRFAMILY: + return "Address family for hostname not supported"; + case GetAddrInfoError::AGAIN: + return "Temporary failure in name resolution"; + case GetAddrInfoError::BADFLAGS: + return "Invalid value for ai_flags"; + case GetAddrInfoError::FAIL: + return "Non-recoverable failure in name resolution"; + case GetAddrInfoError::FAMILY: + return "ai_family not supported"; + case GetAddrInfoError::MEMORY: + return "Memory allocation failure"; + case GetAddrInfoError::NODATA: + return "No address associated with hostname"; + case GetAddrInfoError::NONAME: + return "hostname nor servname provided, or not known"; + case GetAddrInfoError::SERVICE: + return "servname not supported for ai_socktype"; + case GetAddrInfoError::SOCKTYPE: + return "ai_socktype not supported"; + case GetAddrInfoError::SYSTEM: + return "System error returned in errno"; + case GetAddrInfoError::BADHINTS: + return "Invalid value for hints"; + case GetAddrInfoError::PROTOCOL: + return "Resolved protocol is unknown"; + case GetAddrInfoError::OVERFLOW_: + return "Argument buffer overflow"; + default: + return "Unknown error"; + } +} + Network::Domain Translate(Domain domain) { switch (domain) { case Domain::Unspecified: diff --git a/src/core/hle/service/sockets/sockets_translate.h b/src/core/hle/service/sockets/sockets_translate.h index 694868b37..bd6721fd3 100644 --- a/src/core/hle/service/sockets/sockets_translate.h +++ b/src/core/hle/service/sockets/sockets_translate.h @@ -20,6 +20,9 @@ std::pair<s32, Errno> Translate(std::pair<s32, Network::Errno> value); /// Translate abstract getaddrinfo error to guest getaddrinfo error GetAddrInfoError Translate(Network::GetAddrInfoError value); +/// Translate guest error to string +const char* Translate(GetAddrInfoError value); + /// Translate guest domain to abstract domain Network::Domain Translate(Domain domain); diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 3be9b71cf..e04ad19db 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -153,7 +153,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect // Load NSO modules modules.clear(); - const VAddr base_address{GetInteger(process.PageTable().GetCodeRegionStart())}; + const VAddr base_address{GetInteger(process.GetPageTable().GetCodeRegionStart())}; VAddr next_load_addr{base_address}; const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(), system.GetContentProvider()}; diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index 709e2564f..ffe976b94 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp @@ -96,7 +96,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process, } codeset.memory = std::move(program_image); - const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart()); + const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart()); process.LoadModule(std::move(codeset), base_address); LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address); diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 7be6cf5f3..506808b5d 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -203,7 +203,7 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data) // Load codeset for current process codeset.memory = std::move(program_image); - process.LoadModule(std::move(codeset), process.PageTable().GetCodeRegionStart()); + process.LoadModule(std::move(codeset), process.GetPageTable().GetCodeRegionStart()); return true; } diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 79639f5e4..74cc9579f 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -167,7 +167,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S modules.clear(); // Load module - const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart()); + const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart()); if (!LoadModule(process, system, *file, base_address, true, true)) { return {ResultStatus::ErrorLoadingNSO, {}}; } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 805963178..513bc4edb 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -31,10 +31,10 @@ struct Memory::Impl { explicit Impl(Core::System& system_) : system{system_} {} void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) { - current_page_table = &process.PageTable().PageTableImpl(); + current_page_table = &process.GetPageTable().PageTableImpl(); current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer(); - const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth(); + const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth(); system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width); } @@ -73,7 +73,7 @@ struct Memory::Impl { return {}; } - return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr; + return system.DeviceMemory().GetPointer<u8>(paddr + vaddr); } [[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const { @@ -84,7 +84,7 @@ struct Memory::Impl { return {}; } - return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr; + return system.DeviceMemory().GetPointer<u8>(paddr + vaddr); } u8 Read8(const Common::ProcessAddress addr) { @@ -183,13 +183,13 @@ struct Memory::Impl { return string; } - void WalkBlock(const Kernel::KProcess& process, const Common::ProcessAddress addr, - const std::size_t size, auto on_unmapped, auto on_memory, auto on_rasterizer, - auto increment) { - const auto& page_table = process.PageTable().PageTableImpl(); + bool WalkBlock(const Common::ProcessAddress addr, const std::size_t size, auto on_unmapped, + auto on_memory, auto on_rasterizer, auto increment) { + const auto& page_table = system.ApplicationProcess()->GetPageTable().PageTableImpl(); std::size_t remaining_size = size; std::size_t page_index = addr >> YUZU_PAGEBITS; std::size_t page_offset = addr & YUZU_PAGEMASK; + bool user_accessible = true; while (remaining_size) { const std::size_t copy_amount = @@ -200,11 +200,13 @@ struct Memory::Impl { const auto [pointer, type] = page_table.pointers[page_index].PointerType(); switch (type) { case Common::PageType::Unmapped: { + user_accessible = false; on_unmapped(copy_amount, current_vaddr); break; } case Common::PageType::Memory: { - u8* mem_ptr = pointer + page_offset + (page_index << YUZU_PAGEBITS); + u8* mem_ptr = + reinterpret_cast<u8*>(pointer + page_offset + (page_index << YUZU_PAGEBITS)); on_memory(copy_amount, mem_ptr); break; } @@ -227,13 +229,15 @@ struct Memory::Impl { increment(copy_amount); remaining_size -= copy_amount; } + + return user_accessible; } template <bool UNSAFE> - void ReadBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress src_addr, - void* dest_buffer, const std::size_t size) { - WalkBlock( - process, src_addr, size, + bool ReadBlockImpl(const Common::ProcessAddress src_addr, void* dest_buffer, + const std::size_t size) { + return WalkBlock( + src_addr, size, [src_addr, size, &dest_buffer](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) { LOG_ERROR(HW_Memory, @@ -256,14 +260,14 @@ struct Memory::Impl { }); } - void ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, + bool ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, const std::size_t size) { - ReadBlockImpl<false>(*system.ApplicationProcess(), src_addr, dest_buffer, size); + return ReadBlockImpl<false>(src_addr, dest_buffer, size); } - void ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, + bool ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, const std::size_t size) { - ReadBlockImpl<true>(*system.ApplicationProcess(), src_addr, dest_buffer, size); + return ReadBlockImpl<true>(src_addr, dest_buffer, size); } const u8* GetSpan(const VAddr src_addr, const std::size_t size) const { @@ -283,10 +287,10 @@ struct Memory::Impl { } template <bool UNSAFE> - void WriteBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr, - const void* src_buffer, const std::size_t size) { - WalkBlock( - process, dest_addr, size, + bool WriteBlockImpl(const Common::ProcessAddress dest_addr, const void* src_buffer, + const std::size_t size) { + return WalkBlock( + dest_addr, size, [dest_addr, size](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) { LOG_ERROR(HW_Memory, @@ -308,20 +312,19 @@ struct Memory::Impl { }); } - void WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, + bool WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, const std::size_t size) { - WriteBlockImpl<false>(*system.ApplicationProcess(), dest_addr, src_buffer, size); + return WriteBlockImpl<false>(dest_addr, src_buffer, size); } - void WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, + bool WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, const std::size_t size) { - WriteBlockImpl<true>(*system.ApplicationProcess(), dest_addr, src_buffer, size); + return WriteBlockImpl<true>(dest_addr, src_buffer, size); } - void ZeroBlock(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr, - const std::size_t size) { - WalkBlock( - process, dest_addr, size, + bool ZeroBlock(const Common::ProcessAddress dest_addr, const std::size_t size) { + return WalkBlock( + dest_addr, size, [dest_addr, size](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) { LOG_ERROR(HW_Memory, @@ -339,23 +342,23 @@ struct Memory::Impl { [](const std::size_t copy_amount) {}); } - void CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, - Common::ProcessAddress src_addr, const std::size_t size) { - WalkBlock( - process, dest_addr, size, + bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, + const std::size_t size) { + return WalkBlock( + dest_addr, size, [&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) { LOG_ERROR(HW_Memory, "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", GetInteger(current_vaddr), GetInteger(src_addr), size); - ZeroBlock(process, dest_addr, copy_amount); + ZeroBlock(dest_addr, copy_amount); }, [&](const std::size_t copy_amount, const u8* const src_ptr) { - WriteBlockImpl<false>(process, dest_addr, src_ptr, copy_amount); + WriteBlockImpl<false>(dest_addr, src_ptr, copy_amount); }, [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, u8* const host_ptr) { HandleRasterizerDownload(GetInteger(current_vaddr), copy_amount); - WriteBlockImpl<false>(process, dest_addr, host_ptr, copy_amount); + WriteBlockImpl<false>(dest_addr, host_ptr, copy_amount); }, [&](const std::size_t copy_amount) { dest_addr += copy_amount; @@ -364,13 +367,13 @@ struct Memory::Impl { } template <typename Callback> - Result PerformCacheOperation(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, - std::size_t size, Callback&& cb) { + Result PerformCacheOperation(Common::ProcessAddress dest_addr, std::size_t size, + Callback&& cb) { class InvalidMemoryException : public std::exception {}; try { WalkBlock( - process, dest_addr, size, + dest_addr, size, [&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) { LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", GetInteger(current_vaddr)); @@ -387,37 +390,34 @@ struct Memory::Impl { return ResultSuccess; } - Result InvalidateDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, - std::size_t size) { + Result InvalidateDataCache(Common::ProcessAddress dest_addr, std::size_t size) { auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, const std::size_t block_size) { // dc ivac: Invalidate to point of coherency // GPU flush -> CPU invalidate HandleRasterizerDownload(GetInteger(current_vaddr), block_size); }; - return PerformCacheOperation(process, dest_addr, size, on_rasterizer); + return PerformCacheOperation(dest_addr, size, on_rasterizer); } - Result StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, - std::size_t size) { + Result StoreDataCache(Common::ProcessAddress dest_addr, std::size_t size) { auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, const std::size_t block_size) { // dc cvac: Store to point of coherency // CPU flush -> GPU invalidate system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); }; - return PerformCacheOperation(process, dest_addr, size, on_rasterizer); + return PerformCacheOperation(dest_addr, size, on_rasterizer); } - Result FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, - std::size_t size) { + Result FlushDataCache(Common::ProcessAddress dest_addr, std::size_t size) { auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, const std::size_t block_size) { // dc civac: Store to point of coherency, and invalidate from cache // CPU flush -> GPU invalidate system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); }; - return PerformCacheOperation(process, dest_addr, size, on_rasterizer); + return PerformCacheOperation(dest_addr, size, on_rasterizer); } void MarkRegionDebug(u64 vaddr, u64 size, bool debug) { @@ -448,7 +448,7 @@ struct Memory::Impl { break; case Common::PageType::Memory: current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( - nullptr, Common::PageType::DebugMemory); + 0, Common::PageType::DebugMemory); break; default: UNREACHABLE(); @@ -466,7 +466,8 @@ struct Memory::Impl { case Common::PageType::DebugMemory: { u8* const pointer{GetPointerFromDebugMemory(vaddr & ~YUZU_PAGEMASK)}; current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( - pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory); + reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK), + Common::PageType::Memory); break; } default: @@ -506,7 +507,7 @@ struct Memory::Impl { case Common::PageType::DebugMemory: case Common::PageType::Memory: current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( - nullptr, Common::PageType::RasterizerCachedMemory); + 0, Common::PageType::RasterizerCachedMemory); break; case Common::PageType::RasterizerCachedMemory: // There can be more than one GPU region mapped per CPU region, so it's common @@ -534,10 +535,11 @@ struct Memory::Impl { // pagetable after unmapping a VMA. In that case the underlying VMA will no // longer exist, and we should just leave the pagetable entry blank. current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( - nullptr, Common::PageType::Unmapped); + 0, Common::PageType::Unmapped); } else { current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store( - pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory); + reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK), + Common::PageType::Memory); } break; } @@ -584,7 +586,7 @@ struct Memory::Impl { "Mapping memory page without a pointer @ {:016x}", base * YUZU_PAGESIZE); while (base != end) { - page_table.pointers[base].Store(nullptr, type); + page_table.pointers[base].Store(0, type); page_table.backing_addr[base] = 0; page_table.blocks[base] = 0; base += 1; @@ -593,7 +595,8 @@ struct Memory::Impl { auto orig_base = base; while (base != end) { auto host_ptr = - system.DeviceMemory().GetPointer<u8>(target) - (base << YUZU_PAGEBITS); + reinterpret_cast<uintptr_t>(system.DeviceMemory().GetPointer<u8>(target)) - + (base << YUZU_PAGEBITS); auto backing = GetInteger(target) - (base << YUZU_PAGEBITS); page_table.pointers[base].Store(host_ptr, type); page_table.backing_addr[base] = backing; @@ -619,8 +622,8 @@ struct Memory::Impl { // Avoid adding any extra logic to this fast-path block const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw(); - if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { - return &pointer[vaddr]; + if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { + return reinterpret_cast<u8*>(pointer + vaddr); } switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) { case Common::PageType::Unmapped: @@ -808,13 +811,13 @@ void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress b bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const { const Kernel::KProcess& process = *system.ApplicationProcess(); - const auto& page_table = process.PageTable().PageTableImpl(); + const auto& page_table = process.GetPageTable().PageTableImpl(); const size_t page = vaddr >> YUZU_PAGEBITS; if (page >= page_table.pointers.size()) { return false; } const auto [pointer, type] = page_table.pointers[page].PointerType(); - return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory || + return pointer != 0 || type == Common::PageType::RasterizerCachedMemory || type == Common::PageType::DebugMemory; } @@ -899,14 +902,14 @@ std::string Memory::ReadCString(Common::ProcessAddress vaddr, std::size_t max_le return impl->ReadCString(vaddr, max_length); } -void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, +bool Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, const std::size_t size) { - impl->ReadBlock(src_addr, dest_buffer, size); + return impl->ReadBlock(src_addr, dest_buffer, size); } -void Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, +bool Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, const std::size_t size) { - impl->ReadBlockUnsafe(src_addr, dest_buffer, size); + return impl->ReadBlockUnsafe(src_addr, dest_buffer, size); } const u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) const { @@ -917,23 +920,23 @@ u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) { return impl->GetSpan(src_addr, size); } -void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, +bool Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, const std::size_t size) { - impl->WriteBlock(dest_addr, src_buffer, size); + return impl->WriteBlock(dest_addr, src_buffer, size); } -void Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, +bool Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, const std::size_t size) { - impl->WriteBlockUnsafe(dest_addr, src_buffer, size); + return impl->WriteBlockUnsafe(dest_addr, src_buffer, size); } -void Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, +bool Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, const std::size_t size) { - impl->CopyBlock(*system.ApplicationProcess(), dest_addr, src_addr, size); + return impl->CopyBlock(dest_addr, src_addr, size); } -void Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) { - impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size); +bool Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) { + return impl->ZeroBlock(dest_addr, size); } void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) { @@ -941,15 +944,15 @@ void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers } Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { - return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size); + return impl->InvalidateDataCache(dest_addr, size); } Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { - return impl->StoreDataCache(*system.ApplicationProcess(), dest_addr, size); + return impl->StoreDataCache(dest_addr, size); } Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { - return impl->FlushDataCache(*system.ApplicationProcess(), dest_addr, size); + return impl->FlushDataCache(dest_addr, size); } void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) { diff --git a/src/core/memory.h b/src/core/memory.h index ea33c769c..2eb61ffd3 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -24,7 +24,6 @@ class GPUDirtyMemoryManager; } // namespace Core namespace Kernel { -class PhysicalMemory; class KProcess; } // namespace Kernel @@ -330,7 +329,7 @@ public: * @post The range [dest_buffer, size) contains the read bytes from the * current process' address space. */ - void ReadBlock(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size); + bool ReadBlock(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size); /** * Reads a contiguous block of bytes from the current process' address space. @@ -349,7 +348,7 @@ public: * @post The range [dest_buffer, size) contains the read bytes from the * current process' address space. */ - void ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size); + bool ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size); const u8* GetSpan(const VAddr src_addr, const std::size_t size) const; u8* GetSpan(const VAddr src_addr, const std::size_t size); @@ -373,7 +372,7 @@ public: * and will mark that region as invalidated to caches that the active * graphics backend may be maintaining over the course of execution. */ - void WriteBlock(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size); + bool WriteBlock(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size); /** * Writes a range of bytes into the current process' address space at the specified @@ -391,7 +390,7 @@ public: * will be ignored and an error will be logged. * */ - void WriteBlockUnsafe(Common::ProcessAddress dest_addr, const void* src_buffer, + bool WriteBlockUnsafe(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size); /** @@ -405,7 +404,7 @@ public: * @post The range [dest_addr, size) within the process' address space contains the * same data within the range [src_addr, size). */ - void CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, + bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, std::size_t size); /** @@ -418,7 +417,7 @@ public: * @post The range [dest_addr, size) within the process' address space contains the * value 0. */ - void ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size); + bool ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size); /** * Invalidates a range of bytes within the current process' address space at the specified diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 8742dd164..7b52f61a7 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp @@ -199,7 +199,7 @@ void CheatEngine::Initialize() { metadata.process_id = system.ApplicationProcess()->GetProcessId(); metadata.title_id = system.GetApplicationProcessProgramID(); - const auto& page_table = system.ApplicationProcess()->PageTable(); + const auto& page_table = system.ApplicationProcess()->GetPageTable(); metadata.heap_extents = { .base = GetInteger(page_table.GetHeapRegionStart()), .size = page_table.GetHeapRegionSize(), diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 6c3dc7369..b5b3e7eda 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp @@ -117,8 +117,8 @@ json GetProcessorStateDataAuto(Core::System& system) { arm.SaveContext(context); return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32", - GetInteger(process->PageTable().GetCodeRegionStart()), context.sp, - context.pc, context.pstate, context.cpu_registers); + GetInteger(process->GetPageTable().GetCodeRegionStart()), + context.sp, context.pc, context.pstate, context.cpu_registers); } json GetBacktraceData(Core::System& system) { diff --git a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp index d0b145860..07cabca43 100644 --- a/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp +++ b/src/shader_recompiler/ir_opt/ssa_rewrite_pass.cpp @@ -14,12 +14,12 @@ // #include <deque> +#include <map> #include <span> +#include <unordered_map> #include <variant> #include <vector> -#include <boost/container/flat_map.hpp> - #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/opcodes.h" #include "shader_recompiler/frontend/ir/pred.h" @@ -52,7 +52,7 @@ struct IndirectBranchVariable { using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag, OverflowFlagTag, GotoVariable, IndirectBranchVariable>; -using ValueMap = boost::container::flat_map<IR::Block*, IR::Value>; +using ValueMap = std::unordered_map<IR::Block*, IR::Value>; struct DefTable { const IR::Value& Def(IR::Block* block, IR::Reg variable) { @@ -112,7 +112,7 @@ struct DefTable { } std::array<ValueMap, IR::NUM_USER_PREDS> preds; - boost::container::flat_map<u32, ValueMap> goto_vars; + std::unordered_map<u32, ValueMap> goto_vars; ValueMap indirect_branch_var; ValueMap zero_flag; ValueMap sign_flag; @@ -295,8 +295,7 @@ private: return same; } - boost::container::flat_map<IR::Block*, boost::container::flat_map<Variant, IR::Inst*>> - incomplete_phis; + std::unordered_map<IR::Block*, std::map<Variant, IR::Inst*>> incomplete_phis; DefTable current_def; }; diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 6ed4b78f2..f0f450edb 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -442,6 +442,11 @@ void BufferCache<P>::UnbindComputeStorageBuffers() { template <class P> void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset, bool is_written) { + if (ssbo_index >= channel_state->compute_storage_buffers.size()) [[unlikely]] { + LOG_ERROR(HW_GPU, "Storage buffer index {} exceeds maximum storage buffer count", + ssbo_index); + return; + } channel_state->enabled_compute_storage_buffers |= 1U << ssbo_index; channel_state->written_compute_storage_buffers |= (is_written ? 1U : 0U) << ssbo_index; @@ -464,6 +469,11 @@ void BufferCache<P>::UnbindComputeTextureBuffers() { template <class P> void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size, PixelFormat format, bool is_written, bool is_image) { + if (tbo_index >= channel_state->compute_texture_buffers.size()) [[unlikely]] { + LOG_ERROR(HW_GPU, "Texture buffer index {} exceeds maximum texture buffer count", + tbo_index); + return; + } channel_state->enabled_compute_texture_buffers |= 1U << tbo_index; channel_state->written_compute_texture_buffers |= (is_written ? 1U : 0U) << tbo_index; if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index 460fc7551..0b7135d49 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -67,7 +67,7 @@ constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4; constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18; constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8; constexpr u32 NUM_STORAGE_BUFFERS = 16; -constexpr u32 NUM_TEXTURE_BUFFERS = 16; +constexpr u32 NUM_TEXTURE_BUFFERS = 32; constexpr u32 NUM_STAGES = 5; using UniformBufferSizes = std::array<std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES>; diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h index 1528cc1dd..7047e2e63 100644 --- a/src/video_core/query_cache.h +++ b/src/video_core/query_cache.h @@ -103,7 +103,9 @@ public: explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_, Core::Memory::Memory& cpu_memory_) : rasterizer{rasterizer_}, - cpu_memory{cpu_memory_}, streams{{CounterStream{static_cast<QueryCache&>(*this), + // Use reinterpret_cast instead of static_cast as workaround for + // UBSan bug (https://github.com/llvm/llvm-project/issues/59060) + cpu_memory{cpu_memory_}, streams{{CounterStream{reinterpret_cast<QueryCache&>(*this), VideoCore::QueryType::SamplesPassed}}} { (void)slot_async_jobs.insert(); // Null value } diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp index 4a197d65d..f200a650f 100644 --- a/src/video_core/rasterizer_accelerated.cpp +++ b/src/video_core/rasterizer_accelerated.cpp @@ -13,7 +13,8 @@ namespace VideoCore { using namespace Core::Memory; -RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) : cpu_memory{cpu_memory_} {} +RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) + : cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {} RasterizerAccelerated::~RasterizerAccelerated() = default; @@ -26,7 +27,7 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del std::atomic_thread_fence(std::memory_order_acquire); const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE); for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) { - std::atomic_uint16_t& count = cached_pages.at(page >> 2).Count(page); + std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page); if (delta > 0) { ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!"); diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h index 7118b8aff..e6c0ea87a 100644 --- a/src/video_core/rasterizer_accelerated.h +++ b/src/video_core/rasterizer_accelerated.h @@ -41,7 +41,8 @@ private: }; static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!"); - std::array<CacheEntry, 0x2000000> cached_pages; + using CachedPages = std::array<CacheEntry, 0x2000000>; + std::unique_ptr<CachedPages> cached_pages; Core::Memory::Memory& cpu_memory; }; diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index 2d3f58201..4002fa72b 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp @@ -38,8 +38,8 @@ void RendererBase::RequestScreenshot(void* data, std::function<void(bool)> callb LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request"); return; } - auto async_callback{[callback = std::move(callback)](bool invert_y) { - std::thread t{callback, invert_y}; + auto async_callback{[callback_ = std::move(callback)](bool invert_y) { + std::thread t{callback_, invert_y}; t.detach(); }}; renderer_settings.screenshot_bits = data; diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 23a48c6fe..71f720c63 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp @@ -231,24 +231,25 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c } const bool in_parallel = thread_worker != nullptr; const auto backend = device.GetShaderBackend(); - auto func{[this, sources = std::move(sources), sources_spirv = std::move(sources_spirv), + auto func{[this, sources_ = std::move(sources), sources_spirv_ = std::move(sources_spirv), shader_notify, backend, in_parallel, force_context_flush](ShaderContext::Context*) mutable { for (size_t stage = 0; stage < 5; ++stage) { switch (backend) { case Settings::ShaderBackend::GLSL: - if (!sources[stage].empty()) { - source_programs[stage] = CreateProgram(sources[stage], Stage(stage)); + if (!sources_[stage].empty()) { + source_programs[stage] = CreateProgram(sources_[stage], Stage(stage)); } break; case Settings::ShaderBackend::GLASM: - if (!sources[stage].empty()) { - assembly_programs[stage] = CompileProgram(sources[stage], AssemblyStage(stage)); + if (!sources_[stage].empty()) { + assembly_programs[stage] = + CompileProgram(sources_[stage], AssemblyStage(stage)); } break; case Settings::ShaderBackend::SPIRV: - if (!sources_spirv[stage].empty()) { - source_programs[stage] = CreateProgram(sources_spirv[stage], Stage(stage)); + if (!sources_spirv_[stage].empty()) { + source_programs[stage] = CreateProgram(sources_spirv_[stage], Stage(stage)); } break; } diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 0329ed820..7e1d7f92e 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -288,9 +288,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { ComputePipelineKey key; file.read(reinterpret_cast<char*>(&key), sizeof(key)); - queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable { + queue_work([this, key, env_ = std::move(env), &state, &callback](Context* ctx) mutable { ctx->pools.ReleaseContents(); - auto pipeline{CreateComputePipeline(ctx->pools, key, env, true)}; + auto pipeline{CreateComputePipeline(ctx->pools, key, env_, true)}; std::scoped_lock lock{state.mutex}; if (pipeline) { compute_cache.emplace(key, std::move(pipeline)); @@ -305,9 +305,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading, const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) { GraphicsPipelineKey key; file.read(reinterpret_cast<char*>(&key), sizeof(key)); - queue_work([this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable { + queue_work([this, key, envs_ = std::move(envs), &state, &callback](Context* ctx) mutable { boost::container::static_vector<Shader::Environment*, 5> env_ptrs; - for (auto& env : envs) { + for (auto& env : envs_) { env_ptrs.push_back(&env); } ctx->pools.ReleaseContents(); diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 51df18ec3..f8cd2a5d8 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -206,8 +206,8 @@ public: const size_t sub_first_offset = static_cast<size_t>(first % 4) * GetQuadsNum(num_indices); const size_t offset = (sub_first_offset + GetQuadsNum(first)) * 6ULL * BytesPerIndex(index_type); - scheduler.Record([buffer = *buffer, index_type_, offset](vk::CommandBuffer cmdbuf) { - cmdbuf.BindIndexBuffer(buffer, offset, index_type_); + scheduler.Record([buffer_ = *buffer, index_type_, offset](vk::CommandBuffer cmdbuf) { + cmdbuf.BindIndexBuffer(buffer_, offset, index_type_); }); } @@ -528,17 +528,18 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bi buffer_handles.push_back(handle); } if (device.IsExtExtendedDynamicStateSupported()) { - scheduler.Record([bindings = std::move(bindings), - buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { - cmdbuf.BindVertexBuffers2EXT( - bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(), - bindings.offsets.data(), bindings.sizes.data(), bindings.strides.data()); + scheduler.Record([bindings_ = std::move(bindings), + buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { + cmdbuf.BindVertexBuffers2EXT(bindings_.min_index, + bindings_.max_index - bindings_.min_index, + buffer_handles_.data(), bindings_.offsets.data(), + bindings_.sizes.data(), bindings_.strides.data()); }); } else { - scheduler.Record([bindings = std::move(bindings), - buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { - cmdbuf.BindVertexBuffers(bindings.min_index, bindings.max_index - bindings.min_index, - buffer_handles.data(), bindings.offsets.data()); + scheduler.Record([bindings_ = std::move(bindings), + buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { + cmdbuf.BindVertexBuffers(bindings_.min_index, bindings_.max_index - bindings_.min_index, + buffer_handles_.data(), bindings_.offsets.data()); }); } } @@ -573,11 +574,11 @@ void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings< for (u32 index = 0; index < bindings.buffers.size(); ++index) { buffer_handles.push_back(bindings.buffers[index]->Handle()); } - scheduler.Record([bindings = std::move(bindings), - buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { - cmdbuf.BindTransformFeedbackBuffersEXT(0, static_cast<u32>(buffer_handles.size()), - buffer_handles.data(), bindings.offsets.data(), - bindings.sizes.data()); + scheduler.Record([bindings_ = std::move(bindings), + buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) { + cmdbuf.BindTransformFeedbackBuffersEXT(0, static_cast<u32>(buffer_handles_.size()), + buffer_handles_.data(), bindings_.offsets.data(), + bindings_.sizes.data()); }); } diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index d600c4e61..4f84d8497 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -469,9 +469,9 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading ComputePipelineCacheKey key; file.read(reinterpret_cast<char*>(&key), sizeof(key)); - workers.QueueWork([this, key, env = std::move(env), &state, &callback]() mutable { + workers.QueueWork([this, key, env_ = std::move(env), &state, &callback]() mutable { ShaderPools pools; - auto pipeline{CreateComputePipeline(pools, key, env, state.statistics.get(), false)}; + auto pipeline{CreateComputePipeline(pools, key, env_, state.statistics.get(), false)}; std::scoped_lock lock{state.mutex}; if (pipeline) { compute_cache.emplace(key, std::move(pipeline)); @@ -500,10 +500,10 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading (key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) { return; } - workers.QueueWork([this, key, envs = std::move(envs), &state, &callback]() mutable { + workers.QueueWork([this, key, envs_ = std::move(envs), &state, &callback]() mutable { ShaderPools pools; boost::container::static_vector<Shader::Environment*, 5> env_ptrs; - for (auto& env : envs) { + for (auto& env : envs_) { env_ptrs.push_back(&env); } auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs), @@ -702,8 +702,8 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( if (!pipeline || pipeline_cache_filename.empty()) { return pipeline; } - serialization_thread.QueueWork([this, key, env = std::move(env)] { - SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env}, + serialization_thread.QueueWork([this, key, env_ = std::move(env)] { + SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env_}, pipeline_cache_filename, CACHE_VERSION); }); return pipeline; diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index d67490449..29e0b797b 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -98,10 +98,10 @@ HostCounter::HostCounter(QueryCache& cache_, std::shared_ptr<HostCounter> depend : HostCounterBase{std::move(dependency_)}, cache{cache_}, type{type_}, query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} { const vk::Device* logical = &cache.GetDevice().GetLogical(); - cache.GetScheduler().Record([logical, query = query](vk::CommandBuffer cmdbuf) { + cache.GetScheduler().Record([logical, query_ = query](vk::CommandBuffer cmdbuf) { const bool use_precise = Settings::IsGPULevelHigh(); - logical->ResetQueryPool(query.first, query.second, 1); - cmdbuf.BeginQuery(query.first, query.second, + logical->ResetQueryPool(query_.first, query_.second, 1); + cmdbuf.BeginQuery(query_.first, query_.second, use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); }); } @@ -111,8 +111,9 @@ HostCounter::~HostCounter() { } void HostCounter::EndQuery() { - cache.GetScheduler().Record( - [query = query](vk::CommandBuffer cmdbuf) { cmdbuf.EndQuery(query.first, query.second); }); + cache.GetScheduler().Record([query_ = query](vk::CommandBuffer cmdbuf) { + cmdbuf.EndQuery(query_.first, query_.second); + }); } u64 HostCounter::BlockingQuery(bool async) const { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 3aac3cfab..bf6ad6c79 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1412,7 +1412,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS } scheduler->RequestOutsideRenderPassOperationContext(); scheduler->Record([buffers = std::move(buffers_vector), image = *original_image, - aspect_mask = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) { + aspect_mask_ = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) { const VkImageMemoryBarrier read_barrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .pNext = nullptr, @@ -1424,7 +1424,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = image, .subresourceRange{ - .aspectMask = aspect_mask, + .aspectMask = aspect_mask_, .baseMipLevel = 0, .levelCount = VK_REMAINING_MIP_LEVELS, .baseArrayLayer = 0, @@ -1456,7 +1456,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = image, .subresourceRange{ - .aspectMask = aspect_mask, + .aspectMask = aspect_mask_, .baseMipLevel = 0, .levelCount = VK_REMAINING_MIP_LEVELS, .baseArrayLayer = 0, diff --git a/src/web_service/announce_room_json.cpp b/src/web_service/announce_room_json.cpp index 4c3195efd..f1020a5b8 100644 --- a/src/web_service/announce_room_json.cpp +++ b/src/web_service/announce_room_json.cpp @@ -135,11 +135,11 @@ void RoomJson::Delete() { LOG_ERROR(WebService, "Room must be registered to be deleted"); return; } - Common::DetachedTasks::AddTask( - [host{this->host}, username{this->username}, token{this->token}, room_id{this->room_id}]() { - // create a new client here because the this->client might be destroyed. - Client{host, username, token}.DeleteJson(fmt::format("/lobby/{}", room_id), "", false); - }); + Common::DetachedTasks::AddTask([host_{this->host}, username_{this->username}, + token_{this->token}, room_id_{this->room_id}]() { + // create a new client here because the this->client might be destroyed. + Client{host_, username_, token_}.DeleteJson(fmt::format("/lobby/{}", room_id_), "", false); + }); } } // namespace WebService diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 63326968b..9404365b4 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp @@ -235,7 +235,7 @@ GameListWorker::~GameListWorker() = default; void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { using namespace FileSys; - const auto& cache = dynamic_cast<ContentProviderUnion&>(system.GetContentProvider()); + const auto& cache = system.GetContentProviderUnion(); auto installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application, ContentRecordType::Program); @@ -265,7 +265,11 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { std::vector<u8> icon; std::string name; u64 program_id = 0; - loader->ReadProgramId(program_id); + const auto result = loader->ReadProgramId(program_id); + + if (result != Loader::ResultStatus::Success) { + continue; + } const PatchManager patch{program_id, system.GetFileSystemController(), system.GetContentProvider()}; |