Merge pull request #7932 from bunnei/extended-mem-layout

Add extended memory layout (6GB) support and improve KResourceLimit management
This commit is contained in:
bunnei 2022-02-26 01:41:08 -08:00 committed by GitHub
commit 20e9501b0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 91 additions and 55 deletions

View File

@ -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);

View File

@ -466,6 +466,7 @@ struct Values {
// Core
Setting<bool> use_multi_core{true, "use_multi_core"};
Setting<bool> use_extended_memory_layout{false, "use_extended_memory_layout"};
// Cpu
RangedSetting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -5,6 +5,7 @@
#include <random>
#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

View File

@ -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<KProcess*>(arg);
if (owner) {
owner->GetResourceLimit()->Release(LimitableResource::Events, 1);
owner->Close();
}
owner->GetResourceLimit()->Release(LimitableResource::Events, 1);
owner->Close();
}
} // namespace Kernel

View File

@ -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;

View File

@ -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;
}

View File

@ -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() {

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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();

View File

@ -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() {
@ -43,7 +56,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();

View File

@ -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()) {

View File

@ -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();
}

View File

@ -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() &&

View File

@ -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;
};

View File

@ -142,6 +142,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="use_extended_memory_layout">
<property name="text">
<string>Extended memory layout (6GB DRAM)</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle_check_exit">
<property name="text">

View File

@ -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);