diff options
Diffstat (limited to '')
-rw-r--r-- | CMakeLists.txt | 28 | ||||
-rw-r--r-- | CMakeModules/FindDiscordRPC.cmake (renamed from externals/find-modules/FindDiscordRPC.cmake) | 0 | ||||
-rw-r--r-- | CMakeModules/FindFFmpeg.cmake (renamed from externals/find-modules/FindFFmpeg.cmake) | 0 | ||||
-rw-r--r-- | CMakeModules/FindOpus.cmake (renamed from externals/find-modules/FindOpus.cmake) | 0 | ||||
-rw-r--r-- | CMakeModules/Findenet.cmake (renamed from externals/find-modules/Findenet.cmake) | 0 | ||||
-rw-r--r-- | CMakeModules/Findhttplib.cmake (renamed from externals/find-modules/Findhttplib.cmake) | 2 | ||||
-rw-r--r-- | CMakeModules/Findinih.cmake (renamed from externals/find-modules/Findinih.cmake) | 0 | ||||
-rw-r--r-- | CMakeModules/Findlibusb.cmake (renamed from externals/find-modules/Findlibusb.cmake) | 0 | ||||
-rw-r--r-- | CMakeModules/Findlz4.cmake (renamed from externals/find-modules/Findlz4.cmake) | 2 | ||||
-rw-r--r-- | CMakeModules/Findzstd.cmake (renamed from externals/find-modules/Findzstd.cmake) | 2 | ||||
-rw-r--r-- | CMakeModules/WindowsCopyFiles.cmake (renamed from externals/cmake-modules/WindowsCopyFiles.cmake) | 0 | ||||
-rw-r--r-- | externals/CMakeLists.txt | 19 | ||||
-rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/core/hid/emulated_controller.cpp | 20 | ||||
-rw-r--r-- | src/core/hle/kernel/k_code_memory.cpp | 29 | ||||
-rw-r--r-- | src/core/hle/kernel/k_code_memory.h | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/k_memory_manager.cpp | 8 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_group.cpp | 121 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_group.h | 163 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 142 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_table.h | 9 | ||||
-rw-r--r-- | src/core/hle/kernel/k_shared_memory.cpp | 19 | ||||
-rw-r--r-- | src/core/hle/kernel/memory_types.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/nifm/nifm.cpp | 88 | ||||
-rw-r--r-- | src/dedicated_room/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/yuzu/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/yuzu/debugger/controller.cpp | 10 | ||||
-rw-r--r-- | src/yuzu_cmd/CMakeLists.txt | 2 |
29 files changed, 278 insertions, 401 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 55fdf8fcc..cee720940 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,13 +3,8 @@ cmake_minimum_required(VERSION 3.22) -# Dynarmic has cmake_minimum_required(3.12) and we may want to override -# some of its variables, which is only possible in 3.13+ -set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules") -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/find-modules") include(DownloadExternals) include(CMakeDependentOption) @@ -207,42 +202,43 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) # System imported libraries # ======================================================================= -find_package(enet 1.3) +# Enforce the search mode of non-required packages for better and shorter failure messages +find_package(enet 1.3 MODULE) find_package(fmt 9 REQUIRED) -find_package(inih) +find_package(inih MODULE) find_package(lz4 REQUIRED) find_package(nlohmann_json 3.8 REQUIRED) -find_package(Opus 1.3) +find_package(Opus 1.3 MODULE) find_package(ZLIB 1.2 REQUIRED) find_package(zstd 1.5 REQUIRED) if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS) - find_package(Vulkan 1.3.238) + find_package(Vulkan 1.3.238 REQUIRED) endif() if (ENABLE_LIBUSB) - find_package(libusb 1.0.24) + find_package(libusb 1.0.24 MODULE) endif() if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) - find_package(xbyak 6 QUIET) + find_package(xbyak 6 CONFIG) endif() if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) - find_package(dynarmic 6.4.0 QUIET) + find_package(dynarmic 6.4.0 CONFIG) endif() if (ENABLE_CUBEB) - find_package(cubeb QUIET) + find_package(cubeb CONFIG) endif() if (USE_DISCORD_PRESENCE) - find_package(DiscordRPC QUIET) + find_package(DiscordRPC MODULE) endif() if (ENABLE_WEB_SERVICE) - find_package(cpp-jwt 1.4 QUIET) - find_package(httplib 0.11 QUIET) + find_package(cpp-jwt 1.4 CONFIG) + find_package(httplib 0.11 MODULE) endif() if (YUZU_TESTS) diff --git a/externals/find-modules/FindDiscordRPC.cmake b/CMakeModules/FindDiscordRPC.cmake index 44ca9904f..44ca9904f 100644 --- a/externals/find-modules/FindDiscordRPC.cmake +++ b/CMakeModules/FindDiscordRPC.cmake diff --git a/externals/find-modules/FindFFmpeg.cmake b/CMakeModules/FindFFmpeg.cmake index eedf28aea..eedf28aea 100644 --- a/externals/find-modules/FindFFmpeg.cmake +++ b/CMakeModules/FindFFmpeg.cmake diff --git a/externals/find-modules/FindOpus.cmake b/CMakeModules/FindOpus.cmake index 25a44fd87..25a44fd87 100644 --- a/externals/find-modules/FindOpus.cmake +++ b/CMakeModules/FindOpus.cmake diff --git a/externals/find-modules/Findenet.cmake b/CMakeModules/Findenet.cmake index 859a6f386..859a6f386 100644 --- a/externals/find-modules/Findenet.cmake +++ b/CMakeModules/Findenet.cmake diff --git a/externals/find-modules/Findhttplib.cmake b/CMakeModules/Findhttplib.cmake index 4d17cb393..861207eb5 100644 --- a/externals/find-modules/Findhttplib.cmake +++ b/CMakeModules/Findhttplib.cmake @@ -5,7 +5,7 @@ include(FindPackageHandleStandardArgs) find_package(httplib QUIET CONFIG) -if (httplib_FOUND) +if (httplib_CONSIDERED_CONFIGS) find_package_handle_standard_args(httplib CONFIG_MODE) else() find_package(PkgConfig QUIET) diff --git a/externals/find-modules/Findinih.cmake b/CMakeModules/Findinih.cmake index b8d38dcff..b8d38dcff 100644 --- a/externals/find-modules/Findinih.cmake +++ b/CMakeModules/Findinih.cmake diff --git a/externals/find-modules/Findlibusb.cmake b/CMakeModules/Findlibusb.cmake index 0eadce957..0eadce957 100644 --- a/externals/find-modules/Findlibusb.cmake +++ b/CMakeModules/Findlibusb.cmake diff --git a/externals/find-modules/Findlz4.cmake b/CMakeModules/Findlz4.cmake index c82405c59..7a9a02d4e 100644 --- a/externals/find-modules/Findlz4.cmake +++ b/CMakeModules/Findlz4.cmake @@ -4,7 +4,7 @@ include(FindPackageHandleStandardArgs) find_package(lz4 QUIET CONFIG) -if (lz4_FOUND) +if (lz4_CONSIDERED_CONFIGS) find_package_handle_standard_args(lz4 CONFIG_MODE) else() find_package(PkgConfig QUIET) diff --git a/externals/find-modules/Findzstd.cmake b/CMakeModules/Findzstd.cmake index f6eb9643a..ae3ea0865 100644 --- a/externals/find-modules/Findzstd.cmake +++ b/CMakeModules/Findzstd.cmake @@ -4,7 +4,7 @@ include(FindPackageHandleStandardArgs) find_package(zstd QUIET CONFIG) -if (zstd_FOUND) +if (zstd_CONSIDERED_CONFIGS) find_package_handle_standard_args(zstd CONFIG_MODE) else() find_package(PkgConfig QUIET) diff --git a/externals/cmake-modules/WindowsCopyFiles.cmake b/CMakeModules/WindowsCopyFiles.cmake index 08b598365..08b598365 100644 --- a/externals/cmake-modules/WindowsCopyFiles.cmake +++ b/CMakeModules/WindowsCopyFiles.cmake diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index 1b9ae0009..dfd40cba6 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -1,9 +1,9 @@ # SPDX-FileCopyrightText: 2016 Citra Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later -list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules") -list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/externals/find-modules") -include(DownloadExternals) +# Dynarmic has cmake_minimum_required(3.12) and we may want to override +# some of its variables, which is only possible in 3.13+ +set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # xbyak if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak) @@ -12,8 +12,7 @@ endif() # Dynarmic if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic) - set(DYNARMIC_NO_BUNDLED_FMT ON) - set(DYNARMIC_IGNORE_ASSERTS ON CACHE BOOL "" FORCE) + set(DYNARMIC_IGNORE_ASSERTS ON) add_subdirectory(dynarmic EXCLUDE_FROM_ALL) add_library(dynarmic::dynarmic ALIAS dynarmic) endif() @@ -60,10 +59,10 @@ if (YUZU_USE_EXTERNAL_SDL2) Locale Power Render) foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) string(TOUPPER ${_SUB} _OPT) - option(SDL_${_OPT} "" OFF) + set(SDL_${_OPT} OFF) endforeach() - option(HIDAPI "" ON) + set(HIDAPI ON) endif() set(SDL_STATIC ON) set(SDL_SHARED OFF) @@ -83,7 +82,7 @@ endif() # Cubeb if (ENABLE_CUBEB AND NOT TARGET cubeb::cubeb) - set(BUILD_TESTS OFF CACHE BOOL "") + set(BUILD_TESTS OFF) add_subdirectory(cubeb EXCLUDE_FROM_ALL) add_library(cubeb::cubeb ALIAS cubeb) endif() @@ -98,6 +97,7 @@ endif() # Sirit add_subdirectory(sirit EXCLUDE_FROM_ALL) +# httplib if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib) if (NOT WIN32) find_package(OpenSSL 1.1) @@ -108,7 +108,7 @@ if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib) if (WIN32 OR NOT OPENSSL_FOUND) # LibreSSL - set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "") + set(LIBRESSL_SKIP_INSTALL ON) set(OPENSSLDIR "/etc/ssl/") add_subdirectory(libressl EXCLUDE_FROM_ALL) target_include_directories(ssl INTERFACE ./libressl/include) @@ -118,7 +118,6 @@ if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib) DEFINITION OPENSSL_LIBS) endif() - # httplib add_library(httplib INTERFACE) target_include_directories(httplib INTERFACE ./cpp-httplib) target_compile_definitions(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5afdeb5ff..0252c8c31 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -226,7 +226,6 @@ add_library(core STATIC hle/kernel/k_page_buffer.h hle/kernel/k_page_heap.cpp hle/kernel/k_page_heap.h - hle/kernel/k_page_group.cpp hle/kernel/k_page_group.h hle/kernel/k_page_table.cpp hle/kernel/k_page_table.h diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 5587ee097..71364c323 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -11,6 +11,11 @@ namespace Core::HID { constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr s32 HID_TRIGGER_MAX = 0x7fff; +// Use a common UUID for TAS and Virtual Gamepad +constexpr Common::UUID TAS_UUID = + Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; +constexpr Common::UUID VIRTUAL_UUID = + Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {} @@ -348,10 +353,6 @@ void EmulatedController::ReloadInput() { } } - // Use a common UUID for TAS - static constexpr Common::UUID TAS_UUID = Common::UUID{ - {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; - // Register TAS devices. No need to force update for (std::size_t index = 0; index < tas_button_devices.size(); ++index) { if (!tas_button_devices[index]) { @@ -377,10 +378,6 @@ void EmulatedController::ReloadInput() { }); } - // Use a common UUID for Virtual Gamepad - static constexpr Common::UUID VIRTUAL_UUID = Common::UUID{ - {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; - // Register virtual devices. No need to force update for (std::size_t index = 0; index < virtual_button_devices.size(); ++index) { if (!virtual_button_devices[index]) { @@ -780,7 +777,12 @@ void EmulatedController::SetStick(const Common::Input::CallbackStatus& callback, // Only read stick values that have the same uuid or are over the threshold to avoid flapping if (controller.stick_values[index].uuid != uuid) { - if (!stick_value.down && !stick_value.up && !stick_value.left && !stick_value.right) { + const bool is_tas = uuid == TAS_UUID; + if (is_tas && stick_value.x.value == 0 && stick_value.y.value == 0) { + return; + } + if (!is_tas && !stick_value.down && !stick_value.up && !stick_value.left && + !stick_value.right) { return; } } diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp index d9da1e600..4b1c134d4 100644 --- a/src/core/hle/kernel/k_code_memory.cpp +++ b/src/core/hle/kernel/k_code_memory.cpp @@ -27,13 +27,13 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, si auto& page_table = m_owner->PageTable(); // Construct the page group. - m_page_group.emplace(kernel, page_table.GetBlockInfoManager()); + m_page_group = {}; // Lock the memory. - R_TRY(page_table.LockForCodeMemory(std::addressof(*m_page_group), addr, size)) + R_TRY(page_table.LockForCodeMemory(&m_page_group, addr, size)) // Clear the memory. - for (const auto& block : *m_page_group) { + for (const auto& block : m_page_group.Nodes()) { std::memset(device_memory.GetPointer<void>(block.GetAddress()), 0xFF, block.GetSize()); } @@ -51,13 +51,12 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, si 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); + const size_t size = m_page_group.GetNumPages() * PageSize; + m_owner->PageTable().UnlockForCodeMemory(m_address, size, m_page_group); } // Close the page group. - m_page_group->Close(); - m_page_group->Finalize(); + m_page_group = {}; // Close our reference to our owner. m_owner->Close(); @@ -65,7 +64,7 @@ void KCodeMemory::Finalize() { Result KCodeMemory::Map(VAddr address, size_t size) { // Validate the size. - R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); + R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); // Lock ourselves. KScopedLightLock lk(m_lock); @@ -75,7 +74,7 @@ Result KCodeMemory::Map(VAddr address, size_t size) { // Map the memory. R_TRY(kernel.CurrentProcess()->PageTable().MapPages( - address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite)); + address, m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite)); // Mark ourselves as mapped. m_is_mapped = true; @@ -85,13 +84,13 @@ Result KCodeMemory::Map(VAddr address, size_t size) { Result KCodeMemory::Unmap(VAddr address, size_t size) { // Validate the size. - R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); + R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); // Lock ourselves. KScopedLightLock lk(m_lock); // Unmap the memory. - R_TRY(kernel.CurrentProcess()->PageTable().UnmapPages(address, *m_page_group, + R_TRY(kernel.CurrentProcess()->PageTable().UnmapPages(address, m_page_group, KMemoryState::CodeOut)); // Mark ourselves as unmapped. @@ -102,7 +101,7 @@ Result KCodeMemory::Unmap(VAddr address, size_t size) { Result KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm) { // Validate the size. - R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); + R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); // Lock ourselves. KScopedLightLock lk(m_lock); @@ -126,7 +125,7 @@ Result KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission // Map the memory. R_TRY( - m_owner->PageTable().MapPages(address, *m_page_group, KMemoryState::GeneratedCode, k_perm)); + m_owner->PageTable().MapPages(address, m_page_group, KMemoryState::GeneratedCode, k_perm)); // Mark ourselves as mapped. m_is_owner_mapped = true; @@ -136,13 +135,13 @@ Result KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission Result KCodeMemory::UnmapFromOwner(VAddr address, size_t size) { // Validate the size. - R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); + R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); // Lock ourselves. KScopedLightLock lk(m_lock); // Unmap the memory. - R_TRY(m_owner->PageTable().UnmapPages(address, *m_page_group, KMemoryState::GeneratedCode)); + R_TRY(m_owner->PageTable().UnmapPages(address, m_page_group, KMemoryState::GeneratedCode)); // Mark ourselves as unmapped. m_is_owner_mapped = false; diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h index 5b260b385..2e7e1436a 100644 --- a/src/core/hle/kernel/k_code_memory.h +++ b/src/core/hle/kernel/k_code_memory.h @@ -3,8 +3,6 @@ #pragma once -#include <optional> - #include "common/common_types.h" #include "core/device_memory.h" #include "core/hle/kernel/k_auto_object.h" @@ -51,11 +49,11 @@ public: return m_address; } size_t GetSize() const { - return m_is_initialized ? m_page_group->GetNumPages() * PageSize : 0; + return m_is_initialized ? m_page_group.GetNumPages() * PageSize : 0; } private: - std::optional<KPageGroup> m_page_group{}; + KPageGroup m_page_group{}; KProcess* m_owner{}; VAddr m_address{}; KLightLock m_lock; diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index cd6ea388e..bd33571da 100644 --- a/src/core/hle/kernel/k_memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp @@ -223,7 +223,7 @@ Result KMemoryManager::AllocatePageGroupImpl(KPageGroup* out, size_t num_pages, // Ensure that we don't leave anything un-freed. ON_RESULT_FAILURE { - for (const auto& it : *out) { + for (const auto& it : out->Nodes()) { auto& manager = this->GetManager(it.GetAddress()); const size_t node_num_pages = std::min<u64>( it.GetNumPages(), (manager.GetEndAddress() - it.GetAddress()) / PageSize); @@ -285,7 +285,7 @@ Result KMemoryManager::AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 op m_has_optimized_process[static_cast<size_t>(pool)], true)); // Open the first reference to the pages. - for (const auto& block : *out) { + for (const auto& block : out->Nodes()) { PAddr cur_address = block.GetAddress(); size_t remaining_pages = block.GetNumPages(); while (remaining_pages > 0) { @@ -335,7 +335,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32 // Perform optimized memory tracking, if we should. if (optimized) { // Iterate over the allocated blocks. - for (const auto& block : *out) { + for (const auto& block : out->Nodes()) { // Get the block extents. const PAddr block_address = block.GetAddress(); const size_t block_pages = block.GetNumPages(); @@ -391,7 +391,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32 } } else { // Set all the allocated memory. - for (const auto& block : *out) { + for (const auto& block : out->Nodes()) { std::memset(m_system.DeviceMemory().GetPointer<void>(block.GetAddress()), fill_pattern, block.GetSize()); } diff --git a/src/core/hle/kernel/k_page_group.cpp b/src/core/hle/kernel/k_page_group.cpp deleted file mode 100644 index d8c644a33..000000000 --- a/src/core/hle/kernel/k_page_group.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "core/hle/kernel/k_dynamic_resource_manager.h" -#include "core/hle/kernel/k_memory_manager.h" -#include "core/hle/kernel/k_page_group.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/svc_results.h" - -namespace Kernel { - -void KPageGroup::Finalize() { - KBlockInfo* cur = m_first_block; - while (cur != nullptr) { - KBlockInfo* next = cur->GetNext(); - m_manager->Free(cur); - cur = next; - } - - m_first_block = nullptr; - m_last_block = nullptr; -} - -void KPageGroup::CloseAndReset() { - auto& mm = m_kernel.MemoryManager(); - - KBlockInfo* cur = m_first_block; - while (cur != nullptr) { - KBlockInfo* next = cur->GetNext(); - mm.Close(cur->GetAddress(), cur->GetNumPages()); - m_manager->Free(cur); - cur = next; - } - - m_first_block = nullptr; - m_last_block = nullptr; -} - -size_t KPageGroup::GetNumPages() const { - size_t num_pages = 0; - - for (const auto& it : *this) { - num_pages += it.GetNumPages(); - } - - return num_pages; -} - -Result KPageGroup::AddBlock(KPhysicalAddress addr, size_t num_pages) { - // Succeed immediately if we're adding no pages. - R_SUCCEED_IF(num_pages == 0); - - // Check for overflow. - ASSERT(addr < addr + num_pages * PageSize); - - // Try to just append to the last block. - if (m_last_block != nullptr) { - R_SUCCEED_IF(m_last_block->TryConcatenate(addr, num_pages)); - } - - // Allocate a new block. - KBlockInfo* new_block = m_manager->Allocate(); - R_UNLESS(new_block != nullptr, ResultOutOfResource); - - // Initialize the block. - new_block->Initialize(addr, num_pages); - - // Add the block to our list. - if (m_last_block != nullptr) { - m_last_block->SetNext(new_block); - } else { - m_first_block = new_block; - } - m_last_block = new_block; - - R_SUCCEED(); -} - -void KPageGroup::Open() const { - auto& mm = m_kernel.MemoryManager(); - - for (const auto& it : *this) { - mm.Open(it.GetAddress(), it.GetNumPages()); - } -} - -void KPageGroup::OpenFirst() const { - auto& mm = m_kernel.MemoryManager(); - - for (const auto& it : *this) { - mm.OpenFirst(it.GetAddress(), it.GetNumPages()); - } -} - -void KPageGroup::Close() const { - auto& mm = m_kernel.MemoryManager(); - - for (const auto& it : *this) { - mm.Close(it.GetAddress(), it.GetNumPages()); - } -} - -bool KPageGroup::IsEquivalentTo(const KPageGroup& rhs) const { - auto lit = this->begin(); - auto rit = rhs.begin(); - auto lend = this->end(); - auto rend = rhs.end(); - - while (lit != lend && rit != rend) { - if (*lit != *rit) { - return false; - } - - ++lit; - ++rit; - } - - return lit == lend && rit == rend; -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/k_page_group.h b/src/core/hle/kernel/k_page_group.h index c07f17663..316f172f2 100644 --- a/src/core/hle/kernel/k_page_group.h +++ b/src/core/hle/kernel/k_page_group.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -13,23 +13,24 @@ namespace Kernel { -class KBlockInfoManager; -class KernelCore; class KPageGroup; class KBlockInfo { +private: + friend class KPageGroup; + public: - constexpr explicit KBlockInfo() : m_next(nullptr) {} + constexpr KBlockInfo() = default; - constexpr void Initialize(KPhysicalAddress addr, size_t np) { + constexpr void Initialize(PAddr addr, size_t np) { ASSERT(Common::IsAligned(addr, PageSize)); ASSERT(static_cast<u32>(np) == np); - m_page_index = static_cast<u32>(addr / PageSize); + m_page_index = static_cast<u32>(addr) / PageSize; m_num_pages = static_cast<u32>(np); } - constexpr KPhysicalAddress GetAddress() const { + constexpr PAddr GetAddress() const { return m_page_index * PageSize; } constexpr size_t GetNumPages() const { @@ -38,10 +39,10 @@ public: constexpr size_t GetSize() const { return this->GetNumPages() * PageSize; } - constexpr KPhysicalAddress GetEndAddress() const { + constexpr PAddr GetEndAddress() const { return (m_page_index + m_num_pages) * PageSize; } - constexpr KPhysicalAddress GetLastAddress() const { + constexpr PAddr GetLastAddress() const { return this->GetEndAddress() - 1; } @@ -61,8 +62,8 @@ public: return !(*this == rhs); } - constexpr bool IsStrictlyBefore(KPhysicalAddress addr) const { - const KPhysicalAddress end = this->GetEndAddress(); + constexpr bool IsStrictlyBefore(PAddr addr) const { + const PAddr end = this->GetEndAddress(); if (m_page_index != 0 && end == 0) { return false; @@ -71,11 +72,11 @@ public: return end < addr; } - constexpr bool operator<(KPhysicalAddress addr) const { + constexpr bool operator<(PAddr addr) const { return this->IsStrictlyBefore(addr); } - constexpr bool TryConcatenate(KPhysicalAddress addr, size_t np) { + constexpr bool TryConcatenate(PAddr addr, size_t np) { if (addr != 0 && addr == this->GetEndAddress()) { m_num_pages += static_cast<u32>(np); return true; @@ -89,118 +90,96 @@ private: } private: - friend class KPageGroup; - KBlockInfo* m_next{}; u32 m_page_index{}; u32 m_num_pages{}; }; static_assert(sizeof(KBlockInfo) <= 0x10); -class KPageGroup { +class KPageGroup final { public: - class Iterator { + class Node final { public: - using iterator_category = std::forward_iterator_tag; - using value_type = const KBlockInfo; - using difference_type = std::ptrdiff_t; - using pointer = value_type*; - using reference = value_type&; - - constexpr explicit Iterator(pointer n) : m_node(n) {} - - constexpr bool operator==(const Iterator& rhs) const { - return m_node == rhs.m_node; - } - constexpr bool operator!=(const Iterator& rhs) const { - return !(*this == rhs); - } + constexpr Node(u64 addr_, std::size_t num_pages_) : addr{addr_}, num_pages{num_pages_} {} - constexpr pointer operator->() const { - return m_node; - } - constexpr reference operator*() const { - return *m_node; + constexpr u64 GetAddress() const { + return addr; } - constexpr Iterator& operator++() { - m_node = m_node->GetNext(); - return *this; + constexpr std::size_t GetNumPages() const { + return num_pages; } - constexpr Iterator operator++(int) { - const Iterator it{*this}; - ++(*this); - return it; + constexpr std::size_t GetSize() const { + return GetNumPages() * PageSize; } private: - pointer m_node{}; + u64 addr{}; + std::size_t num_pages{}; }; - explicit KPageGroup(KernelCore& kernel, KBlockInfoManager* m) - : m_kernel{kernel}, m_manager{m} {} - ~KPageGroup() { - this->Finalize(); +public: + KPageGroup() = default; + KPageGroup(u64 address, u64 num_pages) { + ASSERT(AddBlock(address, num_pages).IsSuccess()); } - void CloseAndReset(); - void Finalize(); - - Iterator begin() const { - return Iterator{m_first_block}; - } - Iterator end() const { - return Iterator{nullptr}; - } - bool empty() const { - return m_first_block == nullptr; + constexpr std::list<Node>& Nodes() { + return nodes; } - Result AddBlock(KPhysicalAddress addr, size_t num_pages); - void Open() const; - void OpenFirst() const; - void Close() const; - - size_t GetNumPages() const; - - bool IsEquivalentTo(const KPageGroup& rhs) const; - - bool operator==(const KPageGroup& rhs) const { - return this->IsEquivalentTo(rhs); + constexpr const std::list<Node>& Nodes() const { + return nodes; } - bool operator!=(const KPageGroup& rhs) const { - return !(*this == rhs); - } + std::size_t GetNumPages() const { + std::size_t num_pages = 0; + for (const Node& node : nodes) { + num_pages += node.GetNumPages(); + } + return num_pages; + } + + bool IsEqual(KPageGroup& other) const { + auto this_node = nodes.begin(); + auto other_node = other.nodes.begin(); + while (this_node != nodes.end() && other_node != other.nodes.end()) { + if (this_node->GetAddress() != other_node->GetAddress() || + this_node->GetNumPages() != other_node->GetNumPages()) { + return false; + } + this_node = std::next(this_node); + other_node = std::next(other_node); + } -private: - KernelCore& m_kernel; - KBlockInfo* m_first_block{}; - KBlockInfo* m_last_block{}; - KBlockInfoManager* m_manager{}; -}; + return this_node == nodes.end() && other_node == other.nodes.end(); + } -class KScopedPageGroup { -public: - explicit KScopedPageGroup(const KPageGroup* gp) : m_pg(gp) { - if (m_pg) { - m_pg->Open(); + Result AddBlock(u64 address, u64 num_pages) { + if (!num_pages) { + return ResultSuccess; } - } - explicit KScopedPageGroup(const KPageGroup& gp) : KScopedPageGroup(std::addressof(gp)) {} - ~KScopedPageGroup() { - if (m_pg) { - m_pg->Close(); + if (!nodes.empty()) { + const auto node = nodes.back(); + if (node.GetAddress() + node.GetNumPages() * PageSize == address) { + address = node.GetAddress(); + num_pages += node.GetNumPages(); + nodes.pop_back(); + } } + nodes.push_back({address, num_pages}); + return ResultSuccess; } - void CancelClose() { - m_pg = nullptr; + bool Empty() const { + return nodes.empty(); } + void Finalize() {} + private: - const KPageGroup* m_pg{}; + std::list<Node> nodes; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 9c7ac22dc..612fc76fa 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp @@ -100,7 +100,7 @@ constexpr size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceType a KPageTable::KPageTable(Core::System& system_) : m_general_lock{system_.Kernel()}, - m_map_physical_memory_lock{system_.Kernel()}, m_system{system_}, m_kernel{system_.Kernel()} {} + m_map_physical_memory_lock{system_.Kernel()}, m_system{system_} {} KPageTable::~KPageTable() = default; @@ -373,7 +373,7 @@ Result KPageTable::MapProcessCode(VAddr addr, size_t num_pages, KMemoryState sta m_memory_block_slab_manager); // Allocate and open. - KPageGroup pg{m_kernel, m_block_info_manager}; + KPageGroup pg; R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen( &pg, num_pages, KMemoryManager::EncodeOption(KMemoryManager::Pool::Application, m_allocation_option))); @@ -432,7 +432,7 @@ Result KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, size_t si const size_t num_pages = size / PageSize; // Create page groups for the memory being mapped. - KPageGroup pg{m_kernel, m_block_info_manager}; + KPageGroup pg; AddRegionToPages(src_address, num_pages, pg); // Reprotect the source as kernel-read/not mapped. @@ -593,7 +593,7 @@ Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) { const size_t size = num_pages * PageSize; // We're making a new group, not adding to an existing one. - R_UNLESS(pg.empty(), ResultInvalidCurrentMemory); + R_UNLESS(pg.Empty(), ResultInvalidCurrentMemory); // Begin traversal. Common::PageTable::TraversalContext context; @@ -640,10 +640,11 @@ Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) { R_SUCCEED(); } -bool KPageTable::IsValidPageGroup(const KPageGroup& pg, VAddr addr, size_t num_pages) { +bool KPageTable::IsValidPageGroup(const KPageGroup& pg_ll, VAddr addr, size_t num_pages) { ASSERT(this->IsLockedByCurrentThread()); const size_t size = num_pages * PageSize; + const auto& pg = pg_ll.Nodes(); const auto& memory_layout = m_system.Kernel().MemoryLayout(); // Empty groups are necessarily invalid. @@ -941,6 +942,9 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add ON_RESULT_FAILURE { if (cur_mapped_addr != dst_addr) { + // HACK: Manually close the pages. + HACK_ClosePages(dst_addr, (cur_mapped_addr - dst_addr) / PageSize); + ASSERT(Operate(dst_addr, (cur_mapped_addr - dst_addr) / PageSize, KMemoryPermission::None, OperationType::Unmap) .IsSuccess()); @@ -1016,6 +1020,9 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add // Map the page. R_TRY(Operate(cur_mapped_addr, 1, test_perm, OperationType::Map, start_partial_page)); + // HACK: Manually open the pages. + HACK_OpenPages(start_partial_page, 1); + // Update tracking extents. cur_mapped_addr += PageSize; cur_block_addr += PageSize; @@ -1044,6 +1051,9 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add R_TRY(Operate(cur_mapped_addr, cur_block_size / PageSize, test_perm, OperationType::Map, cur_block_addr)); + // HACK: Manually open the pages. + HACK_OpenPages(cur_block_addr, cur_block_size / PageSize); + // Update tracking extents. cur_mapped_addr += cur_block_size; cur_block_addr = next_entry.phys_addr; @@ -1063,6 +1073,9 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add R_TRY(Operate(cur_mapped_addr, last_block_size / PageSize, test_perm, OperationType::Map, cur_block_addr)); + // HACK: Manually open the pages. + HACK_OpenPages(cur_block_addr, last_block_size / PageSize); + // Update tracking extents. cur_mapped_addr += last_block_size; cur_block_addr += last_block_size; @@ -1094,6 +1107,9 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add // Map the page. R_TRY(Operate(cur_mapped_addr, 1, test_perm, OperationType::Map, end_partial_page)); + + // HACK: Manually open the pages. + HACK_OpenPages(end_partial_page, 1); } // Update memory blocks to reflect our changes @@ -1195,6 +1211,9 @@ Result KPageTable::CleanupForIpcServer(VAddr address, size_t size, KMemoryState const size_t aligned_size = aligned_end - aligned_start; const size_t aligned_num_pages = aligned_size / PageSize; + // HACK: Manually close the pages. + HACK_ClosePages(aligned_start, aligned_num_pages); + // Unmap the pages. R_TRY(Operate(aligned_start, aligned_num_pages, KMemoryPermission::None, OperationType::Unmap)); @@ -1482,6 +1501,17 @@ void KPageTable::CleanupForIpcClientOnServerSetupFailure([[maybe_unused]] PageLi } } +void KPageTable::HACK_OpenPages(PAddr phys_addr, size_t num_pages) { + m_system.Kernel().MemoryManager().OpenFirst(phys_addr, num_pages); +} + +void KPageTable::HACK_ClosePages(VAddr virt_addr, size_t num_pages) { + for (size_t index = 0; index < num_pages; ++index) { + const auto paddr = GetPhysicalAddr(virt_addr + (index * PageSize)); + m_system.Kernel().MemoryManager().Close(paddr, 1); + } +} + Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { // Lock the physical memory lock. KScopedLightLock phys_lk(m_map_physical_memory_lock); @@ -1542,7 +1572,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate pages for the new memory. - KPageGroup pg{m_kernel, m_block_info_manager}; + KPageGroup pg; R_TRY(m_system.Kernel().MemoryManager().AllocateForProcess( &pg, (size - mapped_size) / PageSize, m_allocate_option, 0, 0)); @@ -1620,7 +1650,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { KScopedPageTableUpdater updater(this); // Prepare to iterate over the memory. - auto pg_it = pg.begin(); + auto pg_it = pg.Nodes().begin(); PAddr pg_phys_addr = pg_it->GetAddress(); size_t pg_pages = pg_it->GetNumPages(); @@ -1650,6 +1680,9 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { last_unmap_address + 1 - cur_address) / PageSize; + // HACK: Manually close the pages. + HACK_ClosePages(cur_address, cur_pages); + // Unmap. ASSERT(Operate(cur_address, cur_pages, KMemoryPermission::None, OperationType::Unmap) @@ -1670,7 +1703,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { // Release any remaining unmapped memory. m_system.Kernel().MemoryManager().OpenFirst(pg_phys_addr, pg_pages); m_system.Kernel().MemoryManager().Close(pg_phys_addr, pg_pages); - for (++pg_it; pg_it != pg.end(); ++pg_it) { + for (++pg_it; pg_it != pg.Nodes().end(); ++pg_it) { m_system.Kernel().MemoryManager().OpenFirst(pg_it->GetAddress(), pg_it->GetNumPages()); m_system.Kernel().MemoryManager().Close(pg_it->GetAddress(), @@ -1698,7 +1731,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { // Check if we're at the end of the physical block. if (pg_pages == 0) { // Ensure there are more pages to map. - ASSERT(pg_it != pg.end()); + ASSERT(pg_it != pg.Nodes().end()); // Advance our physical block. ++pg_it; @@ -1709,7 +1742,10 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { // Map whatever we can. const size_t cur_pages = std::min(pg_pages, map_pages); R_TRY(Operate(cur_address, cur_pages, KMemoryPermission::UserReadWrite, - OperationType::MapFirst, pg_phys_addr)); + OperationType::Map, pg_phys_addr)); + + // HACK: Manually open the pages. + HACK_OpenPages(pg_phys_addr, cur_pages); // Advance. cur_address += cur_pages * PageSize; @@ -1852,6 +1888,9 @@ Result KPageTable::UnmapPhysicalMemory(VAddr address, size_t size) { last_address + 1 - cur_address) / PageSize; + // HACK: Manually close the pages. + HACK_ClosePages(cur_address, cur_pages); + // Unmap. ASSERT(Operate(cur_address, cur_pages, KMemoryPermission::None, OperationType::Unmap) .IsSuccess()); @@ -1916,7 +1955,7 @@ Result KPageTable::MapMemory(VAddr dst_address, VAddr src_address, size_t size) R_TRY(dst_allocator_result); // Map the memory. - KPageGroup page_linked_list{m_kernel, m_block_info_manager}; + KPageGroup page_linked_list; const size_t num_pages{size / PageSize}; const KMemoryPermission new_src_perm = static_cast<KMemoryPermission>( KMemoryPermission::KernelRead | KMemoryPermission::NotMapped); @@ -1983,14 +2022,14 @@ Result KPageTable::UnmapMemory(VAddr dst_address, VAddr src_address, size_t size num_dst_allocator_blocks); R_TRY(dst_allocator_result); - KPageGroup src_pages{m_kernel, m_block_info_manager}; - KPageGroup dst_pages{m_kernel, m_block_info_manager}; + KPageGroup src_pages; + KPageGroup dst_pages; const size_t num_pages{size / PageSize}; AddRegionToPages(src_address, num_pages, src_pages); AddRegionToPages(dst_address, num_pages, dst_pages); - R_UNLESS(dst_pages.IsEquivalentTo(src_pages), ResultInvalidMemoryRegion); + R_UNLESS(dst_pages.IsEqual(src_pages), ResultInvalidMemoryRegion); { auto block_guard = detail::ScopeExit([&] { MapPages(dst_address, dst_pages, dst_perm); }); @@ -2021,7 +2060,7 @@ Result KPageTable::MapPages(VAddr addr, const KPageGroup& page_linked_list, VAddr cur_addr{addr}; - for (const auto& node : page_linked_list) { + for (const auto& node : page_linked_list.Nodes()) { if (const auto result{ Operate(cur_addr, node.GetNumPages(), perm, OperationType::Map, node.GetAddress())}; result.IsError()) { @@ -2121,7 +2160,7 @@ Result KPageTable::UnmapPages(VAddr addr, const KPageGroup& page_linked_list) { VAddr cur_addr{addr}; - for (const auto& node : page_linked_list) { + for (const auto& node : page_linked_list.Nodes()) { if (const auto result{Operate(cur_addr, node.GetNumPages(), KMemoryPermission::None, OperationType::Unmap)}; result.IsError()) { @@ -2488,13 +2527,13 @@ Result KPageTable::SetHeapSize(VAddr* out, size_t size) { R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Allocate pages for the heap extension. - KPageGroup pg{m_kernel, m_block_info_manager}; + KPageGroup pg; R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen( &pg, allocation_size / PageSize, KMemoryManager::EncodeOption(m_memory_pool, m_allocation_option))); // Clear all the newly allocated pages. - for (const auto& it : pg) { + for (const auto& it : pg.Nodes()) { std::memset(m_system.DeviceMemory().GetPointer<void>(it.GetAddress()), m_heap_fill_value, it.GetSize()); } @@ -2571,23 +2610,11 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(size_t needed_num_pages, size_ if (is_map_only) { R_TRY(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr)); } else { - // Create a page group tohold the pages we allocate. - KPageGroup pg{m_kernel, m_block_info_manager}; - - R_TRY(m_system.Kernel().MemoryManager().AllocateAndOpen( - &pg, needed_num_pages, - KMemoryManager::EncodeOption(m_memory_pool, m_allocation_option))); - - // Ensure that the page group is closed when we're done working with it. - SCOPE_EXIT({ pg.Close(); }); - - // Clear all pages. - for (const auto& it : pg) { - std::memset(m_system.DeviceMemory().GetPointer<void>(it.GetAddress()), - m_heap_fill_value, it.GetSize()); - } - - R_TRY(Operate(addr, needed_num_pages, pg, OperationType::MapGroup)); + KPageGroup page_group; + R_TRY(m_system.Kernel().MemoryManager().AllocateForProcess( + &page_group, needed_num_pages, + KMemoryManager::EncodeOption(m_memory_pool, m_allocation_option), 0, 0)); + R_TRY(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup)); } // Update the blocks. @@ -2768,28 +2795,19 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, const KPageGroup& page_ ASSERT(num_pages > 0); ASSERT(num_pages == page_group.GetNumPages()); - switch (operation) { - case OperationType::MapGroup: { - // We want to maintain a new reference to every page in the group. - KScopedPageGroup spg(page_group); - - for (const auto& node : page_group) { - const size_t size{node.GetNumPages() * PageSize}; + for (const auto& node : page_group.Nodes()) { + const size_t size{node.GetNumPages() * PageSize}; - // Map the pages. + switch (operation) { + case OperationType::MapGroup: m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, size, node.GetAddress()); - - addr += size; + break; + default: + ASSERT(false); + break; } - // We succeeded! We want to persist the reference to the pages. - spg.CancelClose(); - - break; - } - default: - ASSERT(false); - break; + addr += size; } R_SUCCEED(); @@ -2804,29 +2822,13 @@ Result KPageTable::Operate(VAddr addr, size_t num_pages, KMemoryPermission perm, ASSERT(ContainsPages(addr, num_pages)); switch (operation) { - case OperationType::Unmap: { - // Ensure that any pages we track close on exit. - KPageGroup pages_to_close{m_kernel, this->GetBlockInfoManager()}; - SCOPE_EXIT({ pages_to_close.CloseAndReset(); }); - - this->AddRegionToPages(addr, num_pages, pages_to_close); + case OperationType::Unmap: m_system.Memory().UnmapRegion(*m_page_table_impl, addr, num_pages * PageSize); break; - } - case OperationType::MapFirst: case OperationType::Map: { ASSERT(map_addr); ASSERT(Common::IsAligned(map_addr, PageSize)); m_system.Memory().MapMemoryRegion(*m_page_table_impl, addr, num_pages * PageSize, map_addr); - - // Open references to pages, if we should. - if (IsHeapPhysicalAddress(m_kernel.MemoryLayout(), map_addr)) { - if (operation == OperationType::MapFirst) { - m_kernel.MemoryManager().OpenFirst(map_addr, num_pages); - } else { - m_kernel.MemoryManager().Open(map_addr, num_pages); - } - } break; } case OperationType::Separate: { diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index 0a454b05b..f1ca785d7 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h @@ -107,10 +107,6 @@ public: return *m_page_table_impl; } - KBlockInfoManager* GetBlockInfoManager() { - return m_block_info_manager; - } - bool CanContain(VAddr addr, size_t size, KMemoryState state) const; protected: @@ -265,6 +261,10 @@ private: void CleanupForIpcClientOnServerSetupFailure(PageLinkedList* page_list, VAddr address, size_t size, KMemoryPermission prot_perm); + // HACK: These will be removed once we automatically manage page reference counts. + void HACK_OpenPages(PAddr phys_addr, size_t num_pages); + void HACK_ClosePages(VAddr virt_addr, size_t num_pages); + mutable KLightLock m_general_lock; mutable KLightLock m_map_physical_memory_lock; @@ -488,7 +488,6 @@ private: std::unique_ptr<Common::PageTable> m_page_table_impl; Core::System& m_system; - KernelCore& m_kernel; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index 3cf2b5d91..0aa68103c 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp @@ -13,7 +13,10 @@ namespace Kernel { KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {} -KSharedMemory::~KSharedMemory() = default; + +KSharedMemory::~KSharedMemory() { + kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, size); +} Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, Svc::MemoryPermission owner_permission_, @@ -46,8 +49,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o R_UNLESS(physical_address != 0, ResultOutOfMemory); //! Insert the result into our page group. - page_group.emplace(kernel, &kernel.GetSystemSystemResource().GetBlockInfoManager()); - page_group->AddBlock(physical_address, num_pages); + page_group.emplace(physical_address, num_pages); // Commit our reservation. memory_reservation.Commit(); @@ -60,7 +62,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o is_initialized = true; // Clear all pages in the memory. - for (const auto& block : *page_group) { + for (const auto& block : page_group->Nodes()) { std::memset(device_memory_.GetPointer<void>(block.GetAddress()), 0, block.GetSize()); } @@ -69,8 +71,13 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o void KSharedMemory::Finalize() { // Close and finalize the page group. - page_group->Close(); - page_group->Finalize(); + // page_group->Close(); + // page_group->Finalize(); + + //! HACK: Manually close. + for (const auto& block : page_group->Nodes()) { + kernel.MemoryManager().Close(block.GetAddress(), block.GetNumPages()); + } // Release the memory reservation. resource_limit->Release(LimitableResource::PhysicalMemoryMax, size); diff --git a/src/core/hle/kernel/memory_types.h b/src/core/hle/kernel/memory_types.h index 92b8b37ac..3975507bd 100644 --- a/src/core/hle/kernel/memory_types.h +++ b/src/core/hle/kernel/memory_types.h @@ -14,7 +14,4 @@ constexpr std::size_t PageSize{1 << PageBits}; using Page = std::array<u8, PageSize>; -using KPhysicalAddress = PAddr; -using KProcessAddress = VAddr; - } // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index aca442196..788ee2160 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1485,7 +1485,7 @@ static Result MapProcessMemory(Core::System& system, VAddr dst_address, Handle p ResultInvalidMemoryRegion); // Create a new page group. - KPageGroup pg{system.Kernel(), dst_pt.GetBlockInfoManager()}; + KPageGroup pg; R_TRY(src_pt.MakeAndOpenPageGroup( std::addressof(pg), src_address, size / PageSize, KMemoryState::FlagCanMapProcess, KMemoryState::FlagCanMapProcess, KMemoryPermission::None, KMemoryPermission::None, diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 4fa9f51a6..5d32adf64 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -22,15 +22,19 @@ namespace { namespace Service::NIFM { +// This is nn::nifm::RequestState enum class RequestState : u32 { NotSubmitted = 1, - Error = 1, ///< The duplicate 1 is intentional; it means both not submitted and error on HW. - Pending = 2, - Connected = 3, + Invalid = 1, ///< The duplicate 1 is intentional; it means both not submitted and error on HW. + OnHold = 2, + Accepted = 3, + Blocking = 4, }; -enum class InternetConnectionType : u8 { - WiFi = 1, +// This is nn::nifm::NetworkInterfaceType +enum class NetworkInterfaceType : u32 { + Invalid = 0, + WiFi_Ieee80211 = 1, Ethernet = 2, }; @@ -42,14 +46,23 @@ enum class InternetConnectionStatus : u8 { Connected, }; +// This is nn::nifm::NetworkProfileType +enum class NetworkProfileType : u32 { + User, + SsidList, + Temporary, +}; + +// This is nn::nifm::IpAddressSetting struct IpAddressSetting { bool is_automatic{}; - Network::IPv4Address current_address{}; + Network::IPv4Address ip_address{}; Network::IPv4Address subnet_mask{}; - Network::IPv4Address gateway{}; + Network::IPv4Address default_gateway{}; }; static_assert(sizeof(IpAddressSetting) == 0xD, "IpAddressSetting has incorrect size."); +// This is nn::nifm::DnsSetting struct DnsSetting { bool is_automatic{}; Network::IPv4Address primary_dns{}; @@ -57,18 +70,26 @@ struct DnsSetting { }; static_assert(sizeof(DnsSetting) == 0x9, "DnsSetting has incorrect size."); +// This is nn::nifm::AuthenticationSetting +struct AuthenticationSetting { + bool is_enabled{}; + std::array<char, 0x20> user{}; + std::array<char, 0x20> password{}; +}; +static_assert(sizeof(AuthenticationSetting) == 0x41, "AuthenticationSetting has incorrect size."); + +// This is nn::nifm::ProxySetting struct ProxySetting { - bool enabled{}; + bool is_enabled{}; INSERT_PADDING_BYTES(1); u16 port{}; std::array<char, 0x64> proxy_server{}; - bool automatic_auth_enabled{}; - std::array<char, 0x20> user{}; - std::array<char, 0x20> password{}; + AuthenticationSetting authentication{}; INSERT_PADDING_BYTES(1); }; static_assert(sizeof(ProxySetting) == 0xAA, "ProxySetting has incorrect size."); +// This is nn::nifm::IpSettingData struct IpSettingData { IpAddressSetting ip_address_setting{}; DnsSetting dns_setting{}; @@ -101,6 +122,7 @@ static_assert(sizeof(NifmWirelessSettingData) == 0x70, "NifmWirelessSettingData has incorrect size."); #pragma pack(push, 1) +// This is nn::nifm::detail::sf::NetworkProfileData struct SfNetworkProfileData { IpSettingData ip_setting_data{}; u128 uuid{}; @@ -114,13 +136,14 @@ struct SfNetworkProfileData { }; static_assert(sizeof(SfNetworkProfileData) == 0x17C, "SfNetworkProfileData has incorrect size."); +// This is nn::nifm::NetworkProfileData struct NifmNetworkProfileData { u128 uuid{}; std::array<char, 0x40> network_name{}; - u32 unknown_1{}; - u32 unknown_2{}; - u8 unknown_3{}; - u8 unknown_4{}; + NetworkProfileType network_profile_type{}; + NetworkInterfaceType network_interface_type{}; + bool is_auto_connect{}; + bool is_large_capacity{}; INSERT_PADDING_BYTES(2); NifmWirelessSettingData wireless_setting_data{}; IpSettingData ip_setting_data{}; @@ -184,6 +207,7 @@ public: event1 = CreateKEvent(service_context, "IRequest:Event1"); event2 = CreateKEvent(service_context, "IRequest:Event2"); + state = RequestState::NotSubmitted; } ~IRequest() override { @@ -196,7 +220,7 @@ private: LOG_WARNING(Service_NIFM, "(STUBBED) called"); if (state == RequestState::NotSubmitted) { - UpdateState(RequestState::Pending); + UpdateState(RequestState::OnHold); } IPC::ResponseBuilder rb{ctx, 2}; @@ -219,14 +243,14 @@ private: switch (state) { case RequestState::NotSubmitted: return has_connection ? ResultSuccess : ResultNetworkCommunicationDisabled; - case RequestState::Pending: + case RequestState::OnHold: if (has_connection) { - UpdateState(RequestState::Connected); + UpdateState(RequestState::Accepted); } else { - UpdateState(RequestState::Error); + UpdateState(RequestState::Invalid); } return ResultPendingConnection; - case RequestState::Connected: + case RequestState::Accepted: default: return ResultSuccess; } @@ -338,9 +362,9 @@ void IGeneralService::GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { .ip_setting_data{ .ip_address_setting{ .is_automatic{true}, - .current_address{Network::TranslateIPv4(net_iface->ip_address)}, + .ip_address{Network::TranslateIPv4(net_iface->ip_address)}, .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)}, - .gateway{Network::TranslateIPv4(net_iface->gateway)}, + .default_gateway{Network::TranslateIPv4(net_iface->gateway)}, }, .dns_setting{ .is_automatic{true}, @@ -348,12 +372,14 @@ void IGeneralService::GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { .secondary_dns{1, 0, 0, 1}, }, .proxy_setting{ - .enabled{false}, + .is_enabled{false}, .port{}, .proxy_server{}, - .automatic_auth_enabled{}, - .user{}, - .password{}, + .authentication{ + .is_enabled{}, + .user{}, + .password{}, + }, }, .mtu{1500}, }, @@ -370,7 +396,7 @@ void IGeneralService::GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { // When we're connected to a room, spoof the hosts IP address if (auto room_member = network.GetRoomMember().lock()) { if (room_member->IsConnected()) { - network_profile_data.ip_setting_data.ip_address_setting.current_address = + network_profile_data.ip_setting_data.ip_address_setting.ip_address = room_member->GetFakeIpAddress(); } } @@ -444,9 +470,9 @@ void IGeneralService::GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) { return IpConfigInfo{ .ip_address_setting{ .is_automatic{true}, - .current_address{Network::TranslateIPv4(net_iface->ip_address)}, + .ip_address{Network::TranslateIPv4(net_iface->ip_address)}, .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)}, - .gateway{Network::TranslateIPv4(net_iface->gateway)}, + .default_gateway{Network::TranslateIPv4(net_iface->gateway)}, }, .dns_setting{ .is_automatic{true}, @@ -459,7 +485,7 @@ void IGeneralService::GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) { // When we're connected to a room, spoof the hosts IP address if (auto room_member = network.GetRoomMember().lock()) { if (room_member->IsConnected()) { - ip_config_info.ip_address_setting.current_address = room_member->GetFakeIpAddress(); + ip_config_info.ip_address_setting.ip_address = room_member->GetFakeIpAddress(); } } @@ -480,7 +506,7 @@ void IGeneralService::GetInternetConnectionStatus(Kernel::HLERequestContext& ctx LOG_WARNING(Service_NIFM, "(STUBBED) called"); struct Output { - InternetConnectionType type{InternetConnectionType::WiFi}; + u8 type{static_cast<u8>(NetworkInterfaceType::WiFi_Ieee80211)}; u8 wifi_strength{3}; InternetConnectionStatus state{InternetConnectionStatus::Connected}; }; diff --git a/src/dedicated_room/CMakeLists.txt b/src/dedicated_room/CMakeLists.txt index 5bbe1d4b5..136109a0c 100644 --- a/src/dedicated_room/CMakeLists.txt +++ b/src/dedicated_room/CMakeLists.txt @@ -1,8 +1,6 @@ # SPDX-FileCopyrightText: 2017 Citra Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) - add_executable(yuzu-room precompiled_headers.h yuzu_room.cpp diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 4a7d35617..dfc675cc8 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -5,7 +5,6 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) # Set the RPATH for Qt Libraries # This must be done before the `yuzu` target is created diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp index e4bf16a04..19f3775a3 100644 --- a/src/yuzu/debugger/controller.cpp +++ b/src/yuzu/debugger/controller.cpp @@ -93,7 +93,7 @@ void ControllerDialog::ControllerUpdate(Core::HID::ControllerTriggerType type) { case Core::HID::ControllerTriggerType::Button: case Core::HID::ControllerTriggerType::Stick: { const auto buttons_values = controller->GetButtonsValues(); - const auto stick_values = controller->GetSticksValues(); + const auto stick_values = controller->GetSticks(); u64 buttons = 0; std::size_t index = 0; for (const auto& button : buttons_values) { @@ -101,12 +101,12 @@ void ControllerDialog::ControllerUpdate(Core::HID::ControllerTriggerType type) { index++; } const InputCommon::TasInput::TasAnalog left_axis = { - .x = stick_values[Settings::NativeAnalog::LStick].x.value, - .y = stick_values[Settings::NativeAnalog::LStick].y.value, + .x = stick_values.left.x / 32767.f, + .y = stick_values.left.y / 32767.f, }; const InputCommon::TasInput::TasAnalog right_axis = { - .x = stick_values[Settings::NativeAnalog::RStick].x.value, - .y = stick_values[Settings::NativeAnalog::RStick].y.value, + .x = stick_values.right.x / 32767.f, + .y = stick_values.right.y / 32767.f, }; input_subsystem->GetTas()->RecordInput(buttons, left_axis, right_axis); break; diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index 61b6cc4e0..46eddf423 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -1,8 +1,6 @@ # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) - # Credits to Samantas5855 and others for this function. function(create_resource file output filename) # Read hex data from file |