diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 6964a82737..2810cec15f 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 9bee6e10f7..d06b23a145 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -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,
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 3f9a7f44bc..b0cfee3ee0 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/device_memory.cpp b/src/core/device_memory.cpp
index f19c0515ff..e6bc630864 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 c4d17705f1..daeb551eab 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/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
index 6f335c2511..702cacffc0 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 <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
 
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp
index 0720efecef..2e0e8de808 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<KProcess*>(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 3d3ec99e2e..de9732ddf4 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/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 85c5069793..9233261cd9 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 38b4463508..cf1b67428b 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/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index 0c4bba66b4..a84977c685 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 fab6005ff6..d23d16aa4f 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
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 49c0714ed0..797f470217 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) {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 9836809f2f..839171e858 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 62f4cdfb2e..b8c2c6e51d 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() {
@@ -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();
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 88d6ec9083..28d30eee29 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()) {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index d5ba86c033..f915bd856e 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 978a29fe66..08d5444ecd 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 85c1dd4a8c..b6f3bb5edc 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 bfc7711357..c6ef2ab705 100644
--- a/src/yuzu/configuration/configure_general.ui
+++ b/src/yuzu/configuration/configure_general.ui
@@ -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">
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index ff616da702..30963a8bbb 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);