mirror of
https://git.eden-emu.dev/archive/citron
synced 2026-04-20 19:44:30 -04:00
Merge branch 'kernel/12gb-heap-support' into 'main'
kernel: Add 12 GiB heap support See merge request citron/emulator!110
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -120,8 +121,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
static constexpr size_t device_virtual_bits = Traits::device_virtual_bits;
|
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 device_as_size = 1ULL << device_virtual_bits;
|
||||||
static constexpr size_t physical_min_bits = 32;
|
static constexpr size_t physical_min_bits = 32; // 4GB
|
||||||
static constexpr size_t physical_max_bits = 33;
|
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_bits = 12;
|
||||||
static constexpr size_t page_size = 1ULL << page_bits;
|
static constexpr size_t page_size = 1ULL << page_bits;
|
||||||
static constexpr size_t page_mask = page_size - 1ULL;
|
static constexpr size_t page_mask = page_size - 1ULL;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -16,6 +17,8 @@ using namespace Common::Literals;
|
|||||||
constexpr u64 Size_Invalid = UINT64_MAX;
|
constexpr u64 Size_Invalid = UINT64_MAX;
|
||||||
|
|
||||||
// clang-format off
|
// 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{{
|
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 = 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, },
|
{ .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 = 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 = 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 = 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, },
|
{ .bit_width = 36, .address = Size_Invalid, .size = 6_GiB , .type = KAddressSpaceInfo::Type::Alias, },
|
||||||
#ifdef HAS_NCE
|
#ifdef HAS_NCE
|
||||||
// With NCE, we use a 38-bit address space due to memory limitations. This should (safely) truncate ASLR region.
|
// 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, },
|
{ .bit_width = 39, .address = 128_MiB , .size = 512_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, },
|
||||||
#endif
|
#endif
|
||||||
{ .bit_width = 39, .address = Size_Invalid, .size = 64_GiB , .type = KAddressSpaceInfo::Type::MapSmall },
|
{ .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 = 64_GiB , .type = KAddressSpaceInfo::Type::Alias, },
|
||||||
{ .bit_width = 39, .address = Size_Invalid, .size = 2_GiB , .type = KAddressSpaceInfo::Type::Stack, },
|
{ .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 2021 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -158,7 +159,17 @@ void KMemoryLayout::InitializeLinearMemoryRegionTrees(KPhysicalAddress aligned_l
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t KMemoryLayout::GetResourceRegionSizeForInit(bool use_extra_resource) {
|
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);
|
(use_extra_resource ? KernelSlabHeapAdditionalSize + KernelPageBufferAdditionalSize : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#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 MainMemorySize = 4_GiB;
|
||||||
constexpr std::size_t MainMemorySizeMax = 8_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 ReservedEarlyDramSize = 384_KiB;
|
||||||
constexpr std::size_t DramPhysicalAddress = 0x80000000;
|
constexpr std::size_t DramPhysicalAddress = 0x80000000;
|
||||||
|
|
||||||
@@ -53,6 +57,8 @@ constexpr std::size_t KernelPhysicalAddressSpaceSize =
|
|||||||
KernelPhysicalAddressSpaceEnd - KernelPhysicalAddressSpaceBase;
|
KernelPhysicalAddressSpaceEnd - KernelPhysicalAddressSpaceBase;
|
||||||
constexpr std::size_t KernelPhysicalAddressCodeBase = DramPhysicalAddress + ReservedEarlyDramSize;
|
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 KernelPageTableHeapSize = GetMaximumOverheadSize(MainMemorySizeMax);
|
||||||
constexpr std::size_t KernelInitialPageHeapSize = 128_KiB;
|
constexpr std::size_t KernelInitialPageHeapSize = 128_KiB;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -446,8 +447,8 @@ size_t KMemoryManager::Impl::Initialize(KPhysicalAddress address, size_t size,
|
|||||||
// Setup region.
|
// Setup region.
|
||||||
m_pool = p;
|
m_pool = p;
|
||||||
m_management_region = management;
|
m_management_region = management;
|
||||||
m_page_reference_counts.resize(
|
// Allocate page reference counts based on actual managed size, not total memory size
|
||||||
Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize() / PageSize);
|
m_page_reference_counts.resize(size / PageSize);
|
||||||
ASSERT(Common::IsAligned(GetInteger(m_management_region), PageSize));
|
ASSERT(Common::IsAligned(GetInteger(m_management_region), PageSize));
|
||||||
|
|
||||||
// Initialize the manager's KPageHeap.
|
// Initialize the manager's KPageHeap.
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/kernel/k_memory_layout.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/svc.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);
|
LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size);
|
||||||
|
|
||||||
// Validate size.
|
// Validate size.
|
||||||
R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize);
|
// Check alignment and size limits for 12GiB heap support.
|
||||||
R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
|
R_UNLESS((size & 0xfffffffc001fffff) == 0, ResultInvalidSize);
|
||||||
|
R_UNLESS(size < MaxHeapSize, ResultInvalidSize);
|
||||||
|
|
||||||
// Set the heap size.
|
// Set the heap size.
|
||||||
KProcessAddress address{};
|
KProcessAddress address{};
|
||||||
|
|||||||
Reference in New Issue
Block a user