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 <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-10-22 15:06:47 +10:00
parent 8cc5aa143f
commit 9c13799b49
6 changed files with 34 additions and 9 deletions

View File

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

View File

@@ -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 <array>
@@ -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<KAddressSpaceInfo, 13> 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<KAddressSpaceInfo, 13> 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<KAddressSpaceInfo, 13> 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, },
}};

View File

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

View File

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

View File

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

View File

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