From c7019db6f49edae8431480d7a58d47df760d2871 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 21 Feb 2022 12:29:19 -0800 Subject: core: hle: kernel: KResourceLimit: Add a helper function for creating a KResourceLimit for a process. --- src/core/hle/kernel/k_resource_limit.cpp | 19 +++++++++++++++++++ src/core/hle/kernel/k_resource_limit.h | 3 +++ 2 files changed, 22 insertions(+) (limited to 'src') diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index 0c4bba66b..a84977c68 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/assert.h" +#include "core/core.h" #include "core/core_timing.h" #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/svc_results.h" @@ -151,4 +152,22 @@ void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) { } } +KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size) { + auto* resource_limit = KResourceLimit::Create(system.Kernel()); + resource_limit->Initialize(&system.CoreTiming()); + + // Initialize default resource limit values. + // TODO(bunnei): These values are the system defaults, the limits for service processes are + // lower. These should use the correct limit values. + + ASSERT(resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, physical_memory_size) + .IsSuccess()); + ASSERT(resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); + ASSERT(resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); + ASSERT(resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200).IsSuccess()); + ASSERT(resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); + + return resource_limit; +} + } // namespace Kernel diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index fab6005ff..d23d16aa4 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -67,4 +67,7 @@ private: KLightConditionVariable cond_var; const Core::Timing::CoreTiming* core_timing{}; }; + +KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size); + } // namespace Kernel -- cgit v1.2.3 From 57ebcbf2c4574e5d04d5b91ea2918b0d030ac92b Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 21 Feb 2022 12:31:23 -0800 Subject: core: hle: kernel: KEvent: Pass in owner KProcess on event creation. - This is necessary to ensure resource limits are freed from the right process. --- src/core/hle/kernel/k_event.cpp | 14 +++++--------- src/core/hle/kernel/k_event.h | 2 +- src/core/hle/kernel/svc.cpp | 2 +- src/core/hle/service/kernel_helpers.cpp | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp index 0720efece..2e0e8de80 100644 --- a/src/core/hle/kernel/k_event.cpp +++ b/src/core/hle/kernel/k_event.cpp @@ -14,7 +14,7 @@ KEvent::KEvent(KernelCore& kernel_) KEvent::~KEvent() = default; -void KEvent::Initialize(std::string&& name_) { +void KEvent::Initialize(std::string&& name_, KProcess* owner_) { // Increment reference count. // Because reference count is one on creation, this will result // in a reference count of two. Thus, when both readable and @@ -30,10 +30,8 @@ void KEvent::Initialize(std::string&& name_) { writable_event.Initialize(this, name_ + ":Writable"); // Set our owner process. - owner = kernel.CurrentProcess(); - if (owner) { - owner->Open(); - } + owner = owner_; + owner->Open(); // Mark initialized. name = std::move(name_); @@ -47,10 +45,8 @@ void KEvent::Finalize() { void KEvent::PostDestroy(uintptr_t arg) { // Release the event count resource the owner process holds. KProcess* owner = reinterpret_cast(arg); - if (owner) { - owner->GetResourceLimit()->Release(LimitableResource::Events, 1); - owner->Close(); - } + owner->GetResourceLimit()->Release(LimitableResource::Events, 1); + owner->Close(); } } // namespace Kernel diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index 3d3ec99e2..de9732ddf 100644 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h @@ -22,7 +22,7 @@ public: explicit KEvent(KernelCore& kernel_); ~KEvent() override; - void Initialize(std::string&& name); + void Initialize(std::string&& name, KProcess* owner_); void Finalize() override; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9836809f2..839171e85 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -2332,7 +2332,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o R_UNLESS(event != nullptr, ResultOutOfResource); // Initialize the event. - event->Initialize("CreateEvent"); + event->Initialize("CreateEvent", kernel.CurrentProcess()); // Commit the thread reservation. event_reservation.Commit(); diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index 62f4cdfb2..d0c7bc0ce 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp @@ -43,7 +43,7 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { } // Initialize the event. - event->Initialize(std::move(name)); + event->Initialize(std::move(name), process); // Commit the thread reservation. event_reservation.Commit(); -- cgit v1.2.3 From a74fddc98f5c02b2d0be90c6d87ec3779300ee11 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 21 Feb 2022 12:33:17 -0800 Subject: core: hle: kernel: KProcess: Pass in KResourceLimit on process creation. - This allows us to have a resource limit per process, rather than use the global system resource limit. --- src/core/core.cpp | 11 ++++++++++- src/core/hle/kernel/k_process.cpp | 11 +++++------ src/core/hle/kernel/k_process.h | 2 +- src/core/hle/service/kernel_helpers.cpp | 15 ++++++++++++++- 4 files changed, 30 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/core/core.cpp b/src/core/core.cpp index 3f9a7f44b..b0cfee3ee 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -28,7 +28,9 @@ #include "core/file_sys/vfs_real.h" #include "core/hardware_interrupt_manager.h" #include "core/hid/hid_core.h" +#include "core/hle/kernel/k_memory_manager.h" #include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" @@ -252,9 +254,16 @@ struct System::Impl { } telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); + + // Create a resource limit for the process. + const auto physical_memory_size = + kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application); + auto* resource_limit = Kernel::CreateResourceLimitForProcess(system, physical_memory_size); + + // Create the process. auto main_process = Kernel::KProcess::Create(system.Kernel()); ASSERT(Kernel::KProcess::Initialize(main_process, system, "main", - Kernel::KProcess::ProcessType::Userland) + Kernel::KProcess::ProcessType::Userland, resource_limit) .IsSuccess()); const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); if (load_result != Loader::ResultStatus::Success) { diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 85c506979..9233261cd 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -123,12 +123,11 @@ private: }; ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name, - ProcessType type) { + ProcessType type, KResourceLimit* res_limit) { auto& kernel = system.Kernel(); process->name = std::move(process_name); - - process->resource_limit = kernel.GetSystemResourceLimit(); + process->resource_limit = res_limit; process->status = ProcessStatus::Created; process->program_id = 0; process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() @@ -143,9 +142,6 @@ ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::st kernel.AppendNewProcess(process); - // Open a reference to the resource limit. - process->resource_limit->Open(); - // Clear remaining fields. process->num_running_threads = 0; process->is_signaled = false; @@ -153,6 +149,9 @@ ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::st process->is_suspended = false; process->schedule_count = 0; + // Open a reference to the resource limit. + process->resource_limit->Open(); + return ResultSuccess; } diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 38b446350..cf1b67428 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -91,7 +91,7 @@ public: static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; static ResultCode Initialize(KProcess* process, Core::System& system, std::string process_name, - ProcessType type); + ProcessType type, KResourceLimit* res_limit); /// Gets a reference to the process' page table. KPageTable& PageTable() { diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index d0c7bc0ce..b8c2c6e51 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp @@ -3,7 +3,9 @@ // Refer to the license.txt file included. #include "core/core.h" +#include "core/core_timing.h" #include "core/hle/kernel/k_event.h" +#include "core/hle/kernel/k_memory_manager.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/k_resource_limit.h" @@ -15,10 +17,21 @@ namespace Service::KernelHelpers { ServiceContext::ServiceContext(Core::System& system_, std::string name_) : kernel(system_.Kernel()) { + + // Create a resource limit for the process. + const auto physical_memory_size = + kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::System); + auto* resource_limit = Kernel::CreateResourceLimitForProcess(system_, physical_memory_size); + + // Create the process. process = Kernel::KProcess::Create(kernel); ASSERT(Kernel::KProcess::Initialize(process, system_, std::move(name_), - Kernel::KProcess::ProcessType::Userland) + Kernel::KProcess::ProcessType::KernelInternal, + resource_limit) .IsSuccess()); + + // Close reference to our resource limit, as the process opens one. + resource_limit->Close(); } ServiceContext::~ServiceContext() { -- cgit v1.2.3 From ca5e843bf62e6d69b1b476b3925927a20bbffdaf Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 21 Feb 2022 12:34:16 -0800 Subject: core: hle: kernel: Remove resource limit hack for PhysicalMemory. - With prior changes, we now report the correct amount of physical memory available to the emulated process. --- src/core/hle/kernel/kernel.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 49c0714ed..797f47021 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -240,13 +240,6 @@ struct KernelCore::Impl { constexpr u64 secure_applet_memory_size{4_MiB}; ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, secure_applet_memory_size)); - - // This memory seems to be reserved on hardware, but is not reserved/used by yuzu. - // Likely Horizon OS reserved memory - // TODO(ameerj): Derive the memory rather than hardcode it. - constexpr u64 unknown_reserved_memory{0x2f896000}; - ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, - unknown_reserved_memory)); } void InitializePreemption(KernelCore& kernel) { -- cgit v1.2.3 From 70482e6b26d3889517851f57f06c8bed4fbc447a Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 21 Feb 2022 12:35:32 -0800 Subject: settings: Add a new "use_extended_memory_layout" setting. - This will be used to enable emulation of a larger memory arrangement. --- src/common/settings.cpp | 1 + src/common/settings.h | 1 + src/yuzu/configuration/config.cpp | 2 ++ src/yuzu/configuration/configure_general.cpp | 9 +++++++++ src/yuzu/configuration/configure_general.h | 1 + src/yuzu/configuration/configure_general.ui | 7 +++++++ src/yuzu_cmd/config.cpp | 1 + 7 files changed, 22 insertions(+) (limited to 'src') diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 6964a8273..2810cec15 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -167,6 +167,7 @@ void RestoreGlobalState(bool is_powered_on) { // Core values.use_multi_core.SetGlobal(true); + values.use_extended_memory_layout.SetGlobal(true); // CPU values.cpu_accuracy.SetGlobal(true); diff --git a/src/common/settings.h b/src/common/settings.h index 9bee6e10f..d06b23a14 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -466,6 +466,7 @@ struct Values { // Core Setting use_multi_core{true, "use_multi_core"}; + Setting use_extended_memory_layout{false, "use_extended_memory_layout"}; // Cpu RangedSetting cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index d5ba86c03..f915bd856 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -445,6 +445,7 @@ void Config::ReadCoreValues() { qt_config->beginGroup(QStringLiteral("Core")); ReadGlobalSetting(Settings::values.use_multi_core); + ReadGlobalSetting(Settings::values.use_extended_memory_layout); qt_config->endGroup(); } @@ -1019,6 +1020,7 @@ void Config::SaveCoreValues() { qt_config->beginGroup(QStringLiteral("Core")); WriteGlobalSetting(Settings::values.use_multi_core); + WriteGlobalSetting(Settings::values.use_extended_memory_layout); qt_config->endGroup(); } diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 978a29fe6..08d5444ec 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -42,6 +42,9 @@ void ConfigureGeneral::SetConfiguration() { ui->use_multi_core->setEnabled(runtime_lock); ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); + ui->use_extended_memory_layout->setEnabled(runtime_lock); + ui->use_extended_memory_layout->setChecked( + Settings::values.use_extended_memory_layout.GetValue()); ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue()); ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue()); @@ -91,6 +94,9 @@ void ConfigureGeneral::ResetDefaults() { void ConfigureGeneral::ApplyConfiguration() { ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core, use_multi_core); + ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_extended_memory_layout, + ui->use_extended_memory_layout, + use_extended_memory_layout); if (Settings::IsConfiguringGlobal()) { UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); @@ -160,6 +166,9 @@ void ConfigureGeneral::SetupPerGameUI() { Settings::values.use_speed_limit, use_speed_limit); ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core, use_multi_core); + ConfigurationShared::SetColoredTristate(ui->use_extended_memory_layout, + Settings::values.use_extended_memory_layout, + use_extended_memory_layout); connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() { ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() && diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 85c1dd4a8..b6f3bb5ed 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -48,6 +48,7 @@ private: ConfigurationShared::CheckState use_speed_limit; ConfigurationShared::CheckState use_multi_core; + ConfigurationShared::CheckState use_extended_memory_layout; const Core::System& system; }; diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index bfc771135..c6ef2ab70 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui @@ -142,6 +142,13 @@ + + + + Extended memory layout (6GB DRAM) + + + diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index ff616da70..30963a8bb 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -266,6 +266,7 @@ void Config::ReadValues() { // Core ReadSetting("Core", Settings::values.use_multi_core); + ReadSetting("Core", Settings::values.use_extended_memory_layout); // Cpu ReadSetting("Cpu", Settings::values.cpu_accuracy); -- cgit v1.2.3 From c0e45a3c787df9c4c7c99b79a34d31a394bf7b49 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 21 Feb 2022 12:36:34 -0800 Subject: core: device_memory: Use memory size reported by KSystemControl. - That way, we can consolidate the memory layout to one place. --- src/core/device_memory.cpp | 5 ++++- src/core/device_memory.h | 4 ---- src/core/memory.cpp | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/core/device_memory.cpp b/src/core/device_memory.cpp index f19c0515f..e6bc63086 100644 --- a/src/core/device_memory.cpp +++ b/src/core/device_memory.cpp @@ -3,10 +3,13 @@ // Refer to the license.txt file included. #include "core/device_memory.h" +#include "hle/kernel/board/nintendo/nx/k_system_control.h" namespace Core { -DeviceMemory::DeviceMemory() : buffer{DramMemoryMap::Size, 1ULL << 39} {} +DeviceMemory::DeviceMemory() + : buffer{Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize(), + 1ULL << 39} {} DeviceMemory::~DeviceMemory() = default; } // namespace Core diff --git a/src/core/device_memory.h b/src/core/device_memory.h index c4d17705f..daeb551ea 100644 --- a/src/core/device_memory.h +++ b/src/core/device_memory.h @@ -12,12 +12,8 @@ namespace Core { namespace DramMemoryMap { enum : u64 { Base = 0x80000000ULL, - Size = 0x100000000ULL, - End = Base + Size, KernelReserveBase = Base + 0x60000, SlabHeapBase = KernelReserveBase + 0x85000, - SlapHeapSize = 0xa21000, - SlabHeapEnd = SlabHeapBase + SlapHeapSize, }; }; // namespace DramMemoryMap diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 88d6ec908..28d30eee2 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -39,8 +39,7 @@ struct Memory::Impl { void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); - ASSERT_MSG(target >= DramMemoryMap::Base && target < DramMemoryMap::End, - "Out of bounds target: {:016X}", target); + ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", target); MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory); if (Settings::IsFastmemEnabled()) { -- cgit v1.2.3 From 71f62a346d8987302624873b75d1c64903341aa3 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 21 Feb 2022 12:37:59 -0800 Subject: hle: kernel: KSystemControl: Use 6GB memory layout when "use_extended_memory_layout" setting is enabled. - This uses a larger 6GB DRAM memory layout, which is useful for some mods that require more memory. --- .../kernel/board/nintendo/nx/k_system_control.cpp | 24 ++++------------------ 1 file changed, 4 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp index 6f335c251..702cacffc 100644 --- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp +++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp @@ -5,6 +5,7 @@ #include #include "common/literals.h" +#include "common/settings.h" #include "core/hle/kernel/board/nintendo/nx/k_system_control.h" #include "core/hle/kernel/board/nintendo/nx/secure_monitor.h" @@ -28,30 +29,13 @@ namespace { using namespace Common::Literals; -u32 GetMemoryModeForInit() { - return 0x01; -} - u32 GetMemorySizeForInit() { - return 0; + return Settings::values.use_extended_memory_layout ? Smc::MemorySize_6GB : Smc::MemorySize_4GB; } Smc::MemoryArrangement GetMemoryArrangeForInit() { - switch (GetMemoryModeForInit() & 0x3F) { - case 0x01: - default: - return Smc::MemoryArrangement_4GB; - case 0x02: - return Smc::MemoryArrangement_4GBForAppletDev; - case 0x03: - return Smc::MemoryArrangement_4GBForSystemDev; - case 0x11: - return Smc::MemoryArrangement_6GB; - case 0x12: - return Smc::MemoryArrangement_6GBForAppletDev; - case 0x21: - return Smc::MemoryArrangement_8GB; - } + return Settings::values.use_extended_memory_layout ? Smc::MemoryArrangement_6GB + : Smc::MemoryArrangement_4GB; } } // namespace -- cgit v1.2.3