mirror of
https://git.citron-emu.org/citron/emulator
synced 2026-01-03 08:43:47 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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, },
|
||||
}};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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{};
|
||||
|
||||
Reference in New Issue
Block a user