From 9c13799b496d8f27a56903a69f60e20927141fd8 Mon Sep 17 00:00:00 2001 From: Zephyron Date: Wed, 22 Oct 2025 15:06:47 +1000 Subject: [PATCH] kernel: Add 12 GiB heap support - Increased heap region from 8 GiB to 12 GiB - Fixed memory manager page reference count allocation - Made resource region sizing dynamic for >8GB DRAM - Increased physical address space bits to support 16GB Signed-off-by: Zephyron --- src/core/device_memory_manager.h | 5 +++-- src/core/hle/kernel/k_address_space_info.cpp | 7 +++++-- src/core/hle/kernel/k_memory_layout.cpp | 13 ++++++++++++- src/core/hle/kernel/k_memory_layout.h | 6 ++++++ src/core/hle/kernel/k_memory_manager.cpp | 5 +++-- src/core/hle/kernel/svc/svc_physical_memory.cpp | 7 +++++-- 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h index 0568a821b..aaccdc483 100644 --- a/src/core/device_memory_manager.h +++ b/src/core/device_memory_manager.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -120,8 +121,8 @@ public: private: static constexpr size_t device_virtual_bits = Traits::device_virtual_bits; static constexpr size_t device_as_size = 1ULL << device_virtual_bits; - static constexpr size_t physical_min_bits = 32; - static constexpr size_t physical_max_bits = 33; + static constexpr size_t physical_min_bits = 32; // 4GB + static constexpr size_t physical_max_bits = 34; // 16GB (increased to support 12GB+ DRAM) static constexpr size_t page_bits = 12; static constexpr size_t page_size = 1ULL << page_bits; static constexpr size_t page_mask = page_size - 1ULL; diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp index 23258071e..467898fd7 100644 --- a/src/core/hle/kernel/k_address_space_info.cpp +++ b/src/core/hle/kernel/k_address_space_info.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -16,6 +17,8 @@ using namespace Common::Literals; constexpr u64 Size_Invalid = UINT64_MAX; // clang-format off +// Address space layout information for different process address space configurations. +// Heap size increased from 8_GiB to 12_GiB to support games that require larger heap allocations constexpr std::array AddressSpaceInfos{{ { .bit_width = 32, .address = 2_MiB , .size = 1_GiB - 2_MiB , .type = KAddressSpaceInfo::Type::MapSmall, }, { .bit_width = 32, .address = 1_GiB , .size = 4_GiB - 1_GiB , .type = KAddressSpaceInfo::Type::MapLarge, }, @@ -23,7 +26,7 @@ constexpr std::array AddressSpaceInfos{{ { .bit_width = 32, .address = Size_Invalid, .size = 1_GiB , .type = KAddressSpaceInfo::Type::Heap, }, { .bit_width = 36, .address = 128_MiB , .size = 2_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::MapSmall, }, { .bit_width = 36, .address = 2_GiB , .size = 64_GiB - 2_GiB , .type = KAddressSpaceInfo::Type::MapLarge, }, - { .bit_width = 36, .address = Size_Invalid, .size = 8_GiB , .type = KAddressSpaceInfo::Type::Heap, }, + { .bit_width = 36, .address = Size_Invalid, .size = 12_GiB , .type = KAddressSpaceInfo::Type::Heap, }, { .bit_width = 36, .address = Size_Invalid, .size = 6_GiB , .type = KAddressSpaceInfo::Type::Alias, }, #ifdef HAS_NCE // With NCE, we use a 38-bit address space due to memory limitations. This should (safely) truncate ASLR region. @@ -32,7 +35,7 @@ constexpr std::array AddressSpaceInfos{{ { .bit_width = 39, .address = 128_MiB , .size = 512_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, }, #endif { .bit_width = 39, .address = Size_Invalid, .size = 64_GiB , .type = KAddressSpaceInfo::Type::MapSmall }, - { .bit_width = 39, .address = Size_Invalid, .size = 8_GiB , .type = KAddressSpaceInfo::Type::Heap, }, + { .bit_width = 39, .address = Size_Invalid, .size = 12_GiB , .type = KAddressSpaceInfo::Type::Heap, }, { .bit_width = 39, .address = Size_Invalid, .size = 64_GiB , .type = KAddressSpaceInfo::Type::Alias, }, { .bit_width = 39, .address = Size_Invalid, .size = 2_GiB , .type = KAddressSpaceInfo::Type::Stack, }, }}; diff --git a/src/core/hle/kernel/k_memory_layout.cpp b/src/core/hle/kernel/k_memory_layout.cpp index bec714668..1c8eed428 100644 --- a/src/core/hle/kernel/k_memory_layout.cpp +++ b/src/core/hle/kernel/k_memory_layout.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -158,7 +159,17 @@ void KMemoryLayout::InitializeLinearMemoryRegionTrees(KPhysicalAddress aligned_l } size_t KMemoryLayout::GetResourceRegionSizeForInit(bool use_extra_resource) { - return KernelResourceSize + KSystemControl::SecureAppletMemorySize + + // Calculate kernel page table heap size based on actual memory size to support > 8GB DRAM + const size_t actual_memory_size = KSystemControl::Init::GetIntendedMemorySize(); + const size_t actual_pt_heap_size = GetMaximumOverheadSize(actual_memory_size); + + // Use the larger of static or dynamic calculation to ensure sufficient space + const size_t kernel_pt_heap = std::max(KernelPageTableHeapSize, actual_pt_heap_size); + + const size_t base_resource_size = kernel_pt_heap + KernelInitialPageHeapSize + + KernelSlabHeapSize + KernelPageBufferHeapSize; + + return base_resource_size + KSystemControl::SecureAppletMemorySize + (use_extra_resource ? KernelSlabHeapAdditionalSize + KernelPageBufferAdditionalSize : 0); } diff --git a/src/core/hle/kernel/k_memory_layout.h b/src/core/hle/kernel/k_memory_layout.h index d7adb3169..861110ad7 100644 --- a/src/core/hle/kernel/k_memory_layout.h +++ b/src/core/hle/kernel/k_memory_layout.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -27,6 +28,9 @@ constexpr std::size_t GetMaximumOverheadSize(std::size_t size) { constexpr std::size_t MainMemorySize = 4_GiB; constexpr std::size_t MainMemorySizeMax = 8_GiB; +// Maximum heap size that can be allocated by applications (increased to support large games) +constexpr std::size_t MaxHeapSize = 12_GiB; + constexpr std::size_t ReservedEarlyDramSize = 384_KiB; constexpr std::size_t DramPhysicalAddress = 0x80000000; @@ -53,6 +57,8 @@ constexpr std::size_t KernelPhysicalAddressSpaceSize = KernelPhysicalAddressSpaceEnd - KernelPhysicalAddressSpaceBase; constexpr std::size_t KernelPhysicalAddressCodeBase = DramPhysicalAddress + ReservedEarlyDramSize; +// Use MainMemorySizeMax for conservative page table heap allocation +// This keeps kernel overhead reasonable while supporting up to 16GB DRAM constexpr std::size_t KernelPageTableHeapSize = GetMaximumOverheadSize(MainMemorySizeMax); constexpr std::size_t KernelInitialPageHeapSize = 128_KiB; diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index d6bd27296..cc7fd8de1 100644 --- a/src/core/hle/kernel/k_memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -446,8 +447,8 @@ size_t KMemoryManager::Impl::Initialize(KPhysicalAddress address, size_t size, // Setup region. m_pool = p; m_management_region = management; - m_page_reference_counts.resize( - Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize() / PageSize); + // Allocate page reference counts based on actual managed size, not total memory size + m_page_reference_counts.resize(size / PageSize); ASSERT(Common::IsAligned(GetInteger(m_management_region), PageSize)); // Initialize the manager's KPageHeap. diff --git a/src/core/hle/kernel/svc/svc_physical_memory.cpp b/src/core/hle/kernel/svc/svc_physical_memory.cpp index 793e9f8d0..da371fd00 100644 --- a/src/core/hle/kernel/svc/svc_physical_memory.cpp +++ b/src/core/hle/kernel/svc/svc_physical_memory.cpp @@ -1,7 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" +#include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/svc.h" @@ -12,8 +14,9 @@ Result SetHeapSize(Core::System& system, u64* out_address, u64 size) { LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size); // Validate size. - R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize); - R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize); + // Check alignment and size limits for 12GiB heap support. + R_UNLESS((size & 0xfffffffc001fffff) == 0, ResultInvalidSize); + R_UNLESS(size < MaxHeapSize, ResultInvalidSize); // Set the heap size. KProcessAddress address{};