aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/memory
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-02-27 12:48:35 -0700
committerGitHub <noreply@github.com>2021-02-27 12:48:35 -0700
commit09f7c355c6d7e3c7845ba96d9704489d2d5853f4 (patch)
treeb12127263c0e4999f0a6e9edfe7f8f25adef9d37 /src/core/hle/kernel/memory
parentbfa16444640049b2c265fb3f2491252a1d1fe5fd (diff)
parent93e20867b0ab2e737e231a9b5bb29d40947fb311 (diff)
Merge pull request #5953 from bunnei/memory-refactor-1
Kernel Rework: Memory updates and refactoring (Part 1)
Diffstat (limited to 'src/core/hle/kernel/memory')
-rw-r--r--src/core/hle/kernel/memory/address_space_info.cpp119
-rw-r--r--src/core/hle/kernel/memory/address_space_info.h34
-rw-r--r--src/core/hle/kernel/memory/memory_block.h335
-rw-r--r--src/core/hle/kernel/memory/memory_block_manager.cpp223
-rw-r--r--src/core/hle/kernel/memory/memory_block_manager.h66
-rw-r--r--src/core/hle/kernel/memory/memory_layout.h90
-rw-r--r--src/core/hle/kernel/memory/memory_manager.cpp175
-rw-r--r--src/core/hle/kernel/memory/memory_manager.h96
-rw-r--r--src/core/hle/kernel/memory/memory_types.h18
-rw-r--r--src/core/hle/kernel/memory/page_heap.cpp119
-rw-r--r--src/core/hle/kernel/memory/page_heap.h370
-rw-r--r--src/core/hle/kernel/memory/page_linked_list.h92
-rw-r--r--src/core/hle/kernel/memory/page_table.cpp1184
-rw-r--r--src/core/hle/kernel/memory/page_table.h277
-rw-r--r--src/core/hle/kernel/memory/slab_heap.h163
-rw-r--r--src/core/hle/kernel/memory/system_control.cpp40
-rw-r--r--src/core/hle/kernel/memory/system_control.h13
17 files changed, 0 insertions, 3414 deletions
diff --git a/src/core/hle/kernel/memory/address_space_info.cpp b/src/core/hle/kernel/memory/address_space_info.cpp
deleted file mode 100644
index 6cf43ba24..000000000
--- a/src/core/hle/kernel/memory/address_space_info.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
-#include <array>
-
-#include "common/assert.h"
-#include "core/hle/kernel/memory/address_space_info.h"
-
-namespace Kernel::Memory {
-
-namespace {
-
-enum : u64 {
- Size_1_MB = 0x100000,
- Size_2_MB = 2 * Size_1_MB,
- Size_128_MB = 128 * Size_1_MB,
- Size_1_GB = 0x40000000,
- Size_2_GB = 2 * Size_1_GB,
- Size_4_GB = 4 * Size_1_GB,
- Size_6_GB = 6 * Size_1_GB,
- Size_64_GB = 64 * Size_1_GB,
- Size_512_GB = 512 * Size_1_GB,
- Invalid = std::numeric_limits<u64>::max(),
-};
-
-// clang-format off
-constexpr std::array<AddressSpaceInfo, 13> AddressSpaceInfos{{
- { .bit_width = 32, .address = Size_2_MB , .size = Size_1_GB - Size_2_MB , .type = AddressSpaceInfo::Type::Is32Bit, },
- { .bit_width = 32, .address = Size_1_GB , .size = Size_4_GB - Size_1_GB , .type = AddressSpaceInfo::Type::Small64Bit, },
- { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = AddressSpaceInfo::Type::Heap, },
- { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = AddressSpaceInfo::Type::Alias, },
- { .bit_width = 36, .address = Size_128_MB, .size = Size_2_GB - Size_128_MB, .type = AddressSpaceInfo::Type::Is32Bit, },
- { .bit_width = 36, .address = Size_2_GB , .size = Size_64_GB - Size_2_GB , .type = AddressSpaceInfo::Type::Small64Bit, },
- { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Heap, },
- { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Alias, },
- { .bit_width = 39, .address = Size_128_MB, .size = Size_512_GB - Size_128_MB, .type = AddressSpaceInfo::Type::Large64Bit, },
- { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = AddressSpaceInfo::Type::Is32Bit },
- { .bit_width = 39, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Heap, },
- { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = AddressSpaceInfo::Type::Alias, },
- { .bit_width = 39, .address = Invalid , .size = Size_2_GB , .type = AddressSpaceInfo::Type::Stack, },
-}};
-// clang-format on
-
-constexpr bool IsAllowedIndexForAddress(std::size_t index) {
- return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Invalid;
-}
-
-using IndexArray = std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)>;
-
-constexpr IndexArray AddressSpaceIndices32Bit{
- 0, 1, 0, 2, 0, 3,
-};
-
-constexpr IndexArray AddressSpaceIndices36Bit{
- 4, 5, 4, 6, 4, 7,
-};
-
-constexpr IndexArray AddressSpaceIndices39Bit{
- 9, 8, 8, 10, 12, 11,
-};
-
-constexpr bool IsAllowed32BitType(AddressSpaceInfo::Type type) {
- return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit &&
- type != AddressSpaceInfo::Type::Stack;
-}
-
-constexpr bool IsAllowed36BitType(AddressSpaceInfo::Type type) {
- return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit &&
- type != AddressSpaceInfo::Type::Stack;
-}
-
-constexpr bool IsAllowed39BitType(AddressSpaceInfo::Type type) {
- return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Small64Bit;
-}
-
-} // namespace
-
-u64 AddressSpaceInfo::GetAddressSpaceStart(std::size_t width, Type type) {
- const std::size_t index{static_cast<std::size_t>(type)};
- switch (width) {
- case 32:
- ASSERT(IsAllowed32BitType(type));
- ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices32Bit[index]));
- return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].address;
- case 36:
- ASSERT(IsAllowed36BitType(type));
- ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices36Bit[index]));
- return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].address;
- case 39:
- ASSERT(IsAllowed39BitType(type));
- ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[index]));
- return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].address;
- }
- UNREACHABLE();
- return 0;
-}
-
-std::size_t AddressSpaceInfo::GetAddressSpaceSize(std::size_t width, Type type) {
- const std::size_t index{static_cast<std::size_t>(type)};
- switch (width) {
- case 32:
- ASSERT(IsAllowed32BitType(type));
- return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].size;
- case 36:
- ASSERT(IsAllowed36BitType(type));
- return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].size;
- case 39:
- ASSERT(IsAllowed39BitType(type));
- return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].size;
- }
- UNREACHABLE();
- return 0;
-}
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/address_space_info.h b/src/core/hle/kernel/memory/address_space_info.h
deleted file mode 100644
index a4e6e91e5..000000000
--- a/src/core/hle/kernel/memory/address_space_info.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
-#pragma once
-
-#include "common/common_types.h"
-
-namespace Kernel::Memory {
-
-struct AddressSpaceInfo final {
- enum class Type : u32 {
- Is32Bit = 0,
- Small64Bit = 1,
- Large64Bit = 2,
- Heap = 3,
- Stack = 4,
- Alias = 5,
- Count,
- };
-
- static u64 GetAddressSpaceStart(std::size_t width, Type type);
- static std::size_t GetAddressSpaceSize(std::size_t width, Type type);
-
- const std::size_t bit_width{};
- const std::size_t address{};
- const std::size_t size{};
- const Type type{};
-};
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/memory_block.h b/src/core/hle/kernel/memory/memory_block.h
deleted file mode 100644
index 83acece1e..000000000
--- a/src/core/hle/kernel/memory/memory_block.h
+++ /dev/null
@@ -1,335 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
-#pragma once
-
-#include "common/alignment.h"
-#include "common/assert.h"
-#include "common/common_types.h"
-#include "core/hle/kernel/memory/memory_types.h"
-#include "core/hle/kernel/svc_types.h"
-
-namespace Kernel::Memory {
-
-enum class MemoryState : u32 {
- None = 0,
- Mask = 0xFF,
- All = ~None,
-
- FlagCanReprotect = (1 << 8),
- FlagCanDebug = (1 << 9),
- FlagCanUseIpc = (1 << 10),
- FlagCanUseNonDeviceIpc = (1 << 11),
- FlagCanUseNonSecureIpc = (1 << 12),
- FlagMapped = (1 << 13),
- FlagCode = (1 << 14),
- FlagCanAlias = (1 << 15),
- FlagCanCodeAlias = (1 << 16),
- FlagCanTransfer = (1 << 17),
- FlagCanQueryPhysical = (1 << 18),
- FlagCanDeviceMap = (1 << 19),
- FlagCanAlignedDeviceMap = (1 << 20),
- FlagCanIpcUserBuffer = (1 << 21),
- FlagReferenceCounted = (1 << 22),
- FlagCanMapProcess = (1 << 23),
- FlagCanChangeAttribute = (1 << 24),
- FlagCanCodeMemory = (1 << 25),
-
- FlagsData = FlagCanReprotect | FlagCanUseIpc | FlagCanUseNonDeviceIpc | FlagCanUseNonSecureIpc |
- FlagMapped | FlagCanAlias | FlagCanTransfer | FlagCanQueryPhysical |
- FlagCanDeviceMap | FlagCanAlignedDeviceMap | FlagCanIpcUserBuffer |
- FlagReferenceCounted | FlagCanChangeAttribute,
-
- FlagsCode = FlagCanDebug | FlagCanUseIpc | FlagCanUseNonDeviceIpc | FlagCanUseNonSecureIpc |
- FlagMapped | FlagCode | FlagCanQueryPhysical | FlagCanDeviceMap |
- FlagCanAlignedDeviceMap | FlagReferenceCounted,
-
- FlagsMisc = FlagMapped | FlagReferenceCounted | FlagCanQueryPhysical | FlagCanDeviceMap,
-
- Free = static_cast<u32>(Svc::MemoryState::Free),
- Io = static_cast<u32>(Svc::MemoryState::Io) | FlagMapped,
- Static = static_cast<u32>(Svc::MemoryState::Static) | FlagMapped | FlagCanQueryPhysical,
- Code = static_cast<u32>(Svc::MemoryState::Code) | FlagsCode | FlagCanMapProcess,
- CodeData = static_cast<u32>(Svc::MemoryState::CodeData) | FlagsData | FlagCanMapProcess |
- FlagCanCodeMemory,
- Shared = static_cast<u32>(Svc::MemoryState::Shared) | FlagMapped | FlagReferenceCounted,
- Normal = static_cast<u32>(Svc::MemoryState::Normal) | FlagsData | FlagCanCodeMemory,
-
- AliasCode = static_cast<u32>(Svc::MemoryState::AliasCode) | FlagsCode | FlagCanMapProcess |
- FlagCanCodeAlias,
- AliasCodeData = static_cast<u32>(Svc::MemoryState::AliasCodeData) | FlagsData |
- FlagCanMapProcess | FlagCanCodeAlias | FlagCanCodeMemory,
-
- Ipc = static_cast<u32>(Svc::MemoryState::Ipc) | FlagsMisc | FlagCanAlignedDeviceMap |
- FlagCanUseIpc | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
-
- Stack = static_cast<u32>(Svc::MemoryState::Stack) | FlagsMisc | FlagCanAlignedDeviceMap |
- FlagCanUseIpc | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
-
- ThreadLocal =
- static_cast<u32>(Svc::MemoryState::ThreadLocal) | FlagMapped | FlagReferenceCounted,
-
- Transferred = static_cast<u32>(Svc::MemoryState::Transferred) | FlagsMisc |
- FlagCanAlignedDeviceMap | FlagCanChangeAttribute | FlagCanUseIpc |
- FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
-
- SharedTransferred = static_cast<u32>(Svc::MemoryState::SharedTransferred) | FlagsMisc |
- FlagCanAlignedDeviceMap | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
-
- SharedCode = static_cast<u32>(Svc::MemoryState::SharedCode) | FlagMapped |
- FlagReferenceCounted | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
-
- Inaccessible = static_cast<u32>(Svc::MemoryState::Inaccessible),
-
- NonSecureIpc = static_cast<u32>(Svc::MemoryState::NonSecureIpc) | FlagsMisc |
- FlagCanAlignedDeviceMap | FlagCanUseNonSecureIpc | FlagCanUseNonDeviceIpc,
-
- NonDeviceIpc =
- static_cast<u32>(Svc::MemoryState::NonDeviceIpc) | FlagsMisc | FlagCanUseNonDeviceIpc,
-
- Kernel = static_cast<u32>(Svc::MemoryState::Kernel) | FlagMapped,
-
- GeneratedCode = static_cast<u32>(Svc::MemoryState::GeneratedCode) | FlagMapped |
- FlagReferenceCounted | FlagCanDebug,
- CodeOut = static_cast<u32>(Svc::MemoryState::CodeOut) | FlagMapped | FlagReferenceCounted,
-};
-DECLARE_ENUM_FLAG_OPERATORS(MemoryState);
-
-static_assert(static_cast<u32>(MemoryState::Free) == 0x00000000);
-static_assert(static_cast<u32>(MemoryState::Io) == 0x00002001);
-static_assert(static_cast<u32>(MemoryState::Static) == 0x00042002);
-static_assert(static_cast<u32>(MemoryState::Code) == 0x00DC7E03);
-static_assert(static_cast<u32>(MemoryState::CodeData) == 0x03FEBD04);
-static_assert(static_cast<u32>(MemoryState::Normal) == 0x037EBD05);
-static_assert(static_cast<u32>(MemoryState::Shared) == 0x00402006);
-static_assert(static_cast<u32>(MemoryState::AliasCode) == 0x00DD7E08);
-static_assert(static_cast<u32>(MemoryState::AliasCodeData) == 0x03FFBD09);
-static_assert(static_cast<u32>(MemoryState::Ipc) == 0x005C3C0A);
-static_assert(static_cast<u32>(MemoryState::Stack) == 0x005C3C0B);
-static_assert(static_cast<u32>(MemoryState::ThreadLocal) == 0x0040200C);
-static_assert(static_cast<u32>(MemoryState::Transferred) == 0x015C3C0D);
-static_assert(static_cast<u32>(MemoryState::SharedTransferred) == 0x005C380E);
-static_assert(static_cast<u32>(MemoryState::SharedCode) == 0x0040380F);
-static_assert(static_cast<u32>(MemoryState::Inaccessible) == 0x00000010);
-static_assert(static_cast<u32>(MemoryState::NonSecureIpc) == 0x005C3811);
-static_assert(static_cast<u32>(MemoryState::NonDeviceIpc) == 0x004C2812);
-static_assert(static_cast<u32>(MemoryState::Kernel) == 0x00002013);
-static_assert(static_cast<u32>(MemoryState::GeneratedCode) == 0x00402214);
-static_assert(static_cast<u32>(MemoryState::CodeOut) == 0x00402015);
-
-enum class MemoryPermission : u8 {
- None = 0,
- Mask = static_cast<u8>(~None),
-
- Read = 1 << 0,
- Write = 1 << 1,
- Execute = 1 << 2,
-
- ReadAndWrite = Read | Write,
- ReadAndExecute = Read | Execute,
-
- UserMask = static_cast<u8>(Svc::MemoryPermission::Read | Svc::MemoryPermission::Write |
- Svc::MemoryPermission::Execute),
-};
-DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission);
-
-enum class MemoryAttribute : u8 {
- None = 0x00,
- Mask = 0x7F,
- All = Mask,
- DontCareMask = 0x80,
-
- Locked = static_cast<u8>(Svc::MemoryAttribute::Locked),
- IpcLocked = static_cast<u8>(Svc::MemoryAttribute::IpcLocked),
- DeviceShared = static_cast<u8>(Svc::MemoryAttribute::DeviceShared),
- Uncached = static_cast<u8>(Svc::MemoryAttribute::Uncached),
-
- IpcAndDeviceMapped = IpcLocked | DeviceShared,
- LockedAndIpcLocked = Locked | IpcLocked,
- DeviceSharedAndUncached = DeviceShared | Uncached
-};
-DECLARE_ENUM_FLAG_OPERATORS(MemoryAttribute);
-
-static_assert((static_cast<u8>(MemoryAttribute::Mask) &
- static_cast<u8>(MemoryAttribute::DontCareMask)) == 0);
-
-struct MemoryInfo {
- VAddr addr{};
- std::size_t size{};
- MemoryState state{};
- MemoryPermission perm{};
- MemoryAttribute attribute{};
- MemoryPermission original_perm{};
- u16 ipc_lock_count{};
- u16 device_use_count{};
-
- constexpr Svc::MemoryInfo GetSvcMemoryInfo() const {
- return {
- addr,
- size,
- static_cast<Svc::MemoryState>(state & MemoryState::Mask),
- static_cast<Svc::MemoryAttribute>(attribute & MemoryAttribute::Mask),
- static_cast<Svc::MemoryPermission>(perm & MemoryPermission::UserMask),
- ipc_lock_count,
- device_use_count,
- };
- }
-
- constexpr VAddr GetAddress() const {
- return addr;
- }
- constexpr std::size_t GetSize() const {
- return size;
- }
- constexpr std::size_t GetNumPages() const {
- return GetSize() / PageSize;
- }
- constexpr VAddr GetEndAddress() const {
- return GetAddress() + GetSize();
- }
- constexpr VAddr GetLastAddress() const {
- return GetEndAddress() - 1;
- }
-};
-
-class MemoryBlock final {
- friend class MemoryBlockManager;
-
-private:
- VAddr addr{};
- std::size_t num_pages{};
- MemoryState state{MemoryState::None};
- u16 ipc_lock_count{};
- u16 device_use_count{};
- MemoryPermission perm{MemoryPermission::None};
- MemoryPermission original_perm{MemoryPermission::None};
- MemoryAttribute attribute{MemoryAttribute::None};
-
-public:
- static constexpr int Compare(const MemoryBlock& lhs, const MemoryBlock& rhs) {
- if (lhs.GetAddress() < rhs.GetAddress()) {
- return -1;
- } else if (lhs.GetAddress() <= rhs.GetLastAddress()) {
- return 0;
- } else {
- return 1;
- }
- }
-
-public:
- constexpr MemoryBlock() = default;
- constexpr MemoryBlock(VAddr addr_, std::size_t num_pages_, MemoryState state_,
- MemoryPermission perm_, MemoryAttribute attribute_)
- : addr{addr_}, num_pages(num_pages_), state{state_}, perm{perm_}, attribute{attribute_} {}
-
- constexpr VAddr GetAddress() const {
- return addr;
- }
-
- constexpr std::size_t GetNumPages() const {
- return num_pages;
- }
-
- constexpr std::size_t GetSize() const {
- return GetNumPages() * PageSize;
- }
-
- constexpr VAddr GetEndAddress() const {
- return GetAddress() + GetSize();
- }
-
- constexpr VAddr GetLastAddress() const {
- return GetEndAddress() - 1;
- }
-
- constexpr MemoryInfo GetMemoryInfo() const {
- return {
- GetAddress(), GetSize(), state, perm,
- attribute, original_perm, ipc_lock_count, device_use_count,
- };
- }
-
- void ShareToDevice(MemoryPermission /*new_perm*/) {
- ASSERT((attribute & MemoryAttribute::DeviceShared) == MemoryAttribute::DeviceShared ||
- device_use_count == 0);
- attribute |= MemoryAttribute::DeviceShared;
- const u16 new_use_count{++device_use_count};
- ASSERT(new_use_count > 0);
- }
-
- void UnshareToDevice(MemoryPermission /*new_perm*/) {
- ASSERT((attribute & MemoryAttribute::DeviceShared) == MemoryAttribute::DeviceShared);
- const u16 prev_use_count{device_use_count--};
- ASSERT(prev_use_count > 0);
- if (prev_use_count == 1) {
- attribute &= ~MemoryAttribute::DeviceShared;
- }
- }
-
-private:
- constexpr bool HasProperties(MemoryState s, MemoryPermission p, MemoryAttribute a) const {
- constexpr MemoryAttribute AttributeIgnoreMask{MemoryAttribute::DontCareMask |
- MemoryAttribute::IpcLocked |
- MemoryAttribute::DeviceShared};
- return state == s && perm == p &&
- (attribute | AttributeIgnoreMask) == (a | AttributeIgnoreMask);
- }
-
- constexpr bool HasSameProperties(const MemoryBlock& rhs) const {
- return state == rhs.state && perm == rhs.perm && original_perm == rhs.original_perm &&
- attribute == rhs.attribute && ipc_lock_count == rhs.ipc_lock_count &&
- device_use_count == rhs.device_use_count;
- }
-
- constexpr bool Contains(VAddr start) const {
- return GetAddress() <= start && start <= GetEndAddress();
- }
-
- constexpr void Add(std::size_t count) {
- ASSERT(count > 0);
- ASSERT(GetAddress() + count * PageSize - 1 < GetEndAddress() + count * PageSize - 1);
-
- num_pages += count;
- }
-
- constexpr void Update(MemoryState new_state, MemoryPermission new_perm,
- MemoryAttribute new_attribute) {
- ASSERT(original_perm == MemoryPermission::None);
- ASSERT((attribute & MemoryAttribute::IpcLocked) == MemoryAttribute::None);
-
- state = new_state;
- perm = new_perm;
-
- attribute = static_cast<MemoryAttribute>(
- new_attribute |
- (attribute & (MemoryAttribute::IpcLocked | MemoryAttribute::DeviceShared)));
- }
-
- constexpr MemoryBlock Split(VAddr split_addr) {
- ASSERT(GetAddress() < split_addr);
- ASSERT(Contains(split_addr));
- ASSERT(Common::IsAligned(split_addr, PageSize));
-
- MemoryBlock block;
- block.addr = addr;
- block.num_pages = (split_addr - GetAddress()) / PageSize;
- block.state = state;
- block.ipc_lock_count = ipc_lock_count;
- block.device_use_count = device_use_count;
- block.perm = perm;
- block.original_perm = original_perm;
- block.attribute = attribute;
-
- addr = split_addr;
- num_pages -= block.num_pages;
-
- return block;
- }
-};
-static_assert(std::is_trivially_destructible<MemoryBlock>::value);
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/memory_block_manager.cpp b/src/core/hle/kernel/memory/memory_block_manager.cpp
deleted file mode 100644
index 0732fa5a1..000000000
--- a/src/core/hle/kernel/memory/memory_block_manager.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/kernel/memory/memory_block_manager.h"
-#include "core/hle/kernel/memory/memory_types.h"
-
-namespace Kernel::Memory {
-
-MemoryBlockManager::MemoryBlockManager(VAddr start_addr, VAddr end_addr)
- : start_addr{start_addr}, end_addr{end_addr} {
- const u64 num_pages{(end_addr - start_addr) / PageSize};
- memory_block_tree.emplace_back(start_addr, num_pages, MemoryState::Free, MemoryPermission::None,
- MemoryAttribute::None);
-}
-
-MemoryBlockManager::iterator MemoryBlockManager::FindIterator(VAddr addr) {
- auto node{memory_block_tree.begin()};
- while (node != end()) {
- const VAddr end_addr{node->GetNumPages() * PageSize + node->GetAddress()};
- if (node->GetAddress() <= addr && end_addr - 1 >= addr) {
- return node;
- }
- node = std::next(node);
- }
- return end();
-}
-
-VAddr MemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_num_pages,
- std::size_t num_pages, std::size_t align, std::size_t offset,
- std::size_t guard_pages) {
- if (num_pages == 0) {
- return {};
- }
-
- const VAddr region_end{region_start + region_num_pages * PageSize};
- const VAddr region_last{region_end - 1};
- for (auto it{FindIterator(region_start)}; it != memory_block_tree.cend(); it++) {
- const auto info{it->GetMemoryInfo()};
- if (region_last < info.GetAddress()) {
- break;
- }
-
- if (info.state != MemoryState::Free) {
- continue;
- }
-
- VAddr area{(info.GetAddress() <= region_start) ? region_start : info.GetAddress()};
- area += guard_pages * PageSize;
-
- const VAddr offset_area{Common::AlignDown(area, align) + offset};
- area = (area <= offset_area) ? offset_area : offset_area + align;
-
- const VAddr area_end{area + num_pages * PageSize + guard_pages * PageSize};
- const VAddr area_last{area_end - 1};
-
- if (info.GetAddress() <= area && area < area_last && area_last <= region_last &&
- area_last <= info.GetLastAddress()) {
- return area;
- }
- }
-
- return {};
-}
-
-void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState prev_state,
- MemoryPermission prev_perm, MemoryAttribute prev_attribute,
- MemoryState state, MemoryPermission perm,
- MemoryAttribute attribute) {
- const VAddr end_addr{addr + num_pages * PageSize};
- iterator node{memory_block_tree.begin()};
-
- prev_attribute |= MemoryAttribute::IpcAndDeviceMapped;
-
- while (node != memory_block_tree.end()) {
- MemoryBlock* block{&(*node)};
- iterator next_node{std::next(node)};
- const VAddr cur_addr{block->GetAddress()};
- const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
-
- if (addr < cur_end_addr && cur_addr < end_addr) {
- if (!block->HasProperties(prev_state, prev_perm, prev_attribute)) {
- node = next_node;
- continue;
- }
-
- iterator new_node{node};
- if (addr > cur_addr) {
- memory_block_tree.insert(node, block->Split(addr));
- }
-
- if (end_addr < cur_end_addr) {
- new_node = memory_block_tree.insert(node, block->Split(end_addr));
- }
-
- new_node->Update(state, perm, attribute);
-
- MergeAdjacent(new_node, next_node);
- }
-
- if (cur_end_addr - 1 >= end_addr - 1) {
- break;
- }
-
- node = next_node;
- }
-}
-
-void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState state,
- MemoryPermission perm, MemoryAttribute attribute) {
- const VAddr end_addr{addr + num_pages * PageSize};
- iterator node{memory_block_tree.begin()};
-
- while (node != memory_block_tree.end()) {
- MemoryBlock* block{&(*node)};
- iterator next_node{std::next(node)};
- const VAddr cur_addr{block->GetAddress()};
- const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
-
- if (addr < cur_end_addr && cur_addr < end_addr) {
- iterator new_node{node};
-
- if (addr > cur_addr) {
- memory_block_tree.insert(node, block->Split(addr));
- }
-
- if (end_addr < cur_end_addr) {
- new_node = memory_block_tree.insert(node, block->Split(end_addr));
- }
-
- new_node->Update(state, perm, attribute);
-
- MergeAdjacent(new_node, next_node);
- }
-
- if (cur_end_addr - 1 >= end_addr - 1) {
- break;
- }
-
- node = next_node;
- }
-}
-
-void MemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func,
- MemoryPermission perm) {
- const VAddr end_addr{addr + num_pages * PageSize};
- iterator node{memory_block_tree.begin()};
-
- while (node != memory_block_tree.end()) {
- MemoryBlock* block{&(*node)};
- iterator next_node{std::next(node)};
- const VAddr cur_addr{block->GetAddress()};
- const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
-
- if (addr < cur_end_addr && cur_addr < end_addr) {
- iterator new_node{node};
-
- if (addr > cur_addr) {
- memory_block_tree.insert(node, block->Split(addr));
- }
-
- if (end_addr < cur_end_addr) {
- new_node = memory_block_tree.insert(node, block->Split(end_addr));
- }
-
- lock_func(new_node, perm);
-
- MergeAdjacent(new_node, next_node);
- }
-
- if (cur_end_addr - 1 >= end_addr - 1) {
- break;
- }
-
- node = next_node;
- }
-}
-
-void MemoryBlockManager::IterateForRange(VAddr start, VAddr end, IterateFunc&& func) {
- const_iterator it{FindIterator(start)};
- MemoryInfo info{};
- do {
- info = it->GetMemoryInfo();
- func(info);
- it = std::next(it);
- } while (info.addr + info.size - 1 < end - 1 && it != cend());
-}
-
-void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) {
- MemoryBlock* block{&(*it)};
-
- auto EraseIt = [&](const iterator it_to_erase) {
- if (next_it == it_to_erase) {
- next_it = std::next(next_it);
- }
- memory_block_tree.erase(it_to_erase);
- };
-
- if (it != memory_block_tree.begin()) {
- MemoryBlock* prev{&(*std::prev(it))};
-
- if (block->HasSameProperties(*prev)) {
- const iterator prev_it{std::prev(it)};
-
- prev->Add(block->GetNumPages());
- EraseIt(it);
-
- it = prev_it;
- block = prev;
- }
- }
-
- if (it != cend()) {
- const MemoryBlock* const next{&(*std::next(it))};
-
- if (block->HasSameProperties(*next)) {
- block->Add(next->GetNumPages());
- EraseIt(std::next(it));
- }
- }
-}
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/memory_block_manager.h b/src/core/hle/kernel/memory/memory_block_manager.h
deleted file mode 100644
index f57d1bbcc..000000000
--- a/src/core/hle/kernel/memory/memory_block_manager.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <functional>
-#include <list>
-
-#include "common/common_types.h"
-#include "core/hle/kernel/memory/memory_block.h"
-
-namespace Kernel::Memory {
-
-class MemoryBlockManager final {
-public:
- using MemoryBlockTree = std::list<MemoryBlock>;
- using iterator = MemoryBlockTree::iterator;
- using const_iterator = MemoryBlockTree::const_iterator;
-
-public:
- MemoryBlockManager(VAddr start_addr, VAddr end_addr);
-
- iterator end() {
- return memory_block_tree.end();
- }
- const_iterator end() const {
- return memory_block_tree.end();
- }
- const_iterator cend() const {
- return memory_block_tree.cend();
- }
-
- iterator FindIterator(VAddr addr);
-
- VAddr FindFreeArea(VAddr region_start, std::size_t region_num_pages, std::size_t num_pages,
- std::size_t align, std::size_t offset, std::size_t guard_pages);
-
- void Update(VAddr addr, std::size_t num_pages, MemoryState prev_state,
- MemoryPermission prev_perm, MemoryAttribute prev_attribute, MemoryState state,
- MemoryPermission perm, MemoryAttribute attribute);
-
- void Update(VAddr addr, std::size_t num_pages, MemoryState state,
- MemoryPermission perm = MemoryPermission::None,
- MemoryAttribute attribute = MemoryAttribute::None);
-
- using LockFunc = std::function<void(iterator, MemoryPermission)>;
- void UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, MemoryPermission perm);
-
- using IterateFunc = std::function<void(const MemoryInfo&)>;
- void IterateForRange(VAddr start, VAddr end, IterateFunc&& func);
-
- MemoryBlock& FindBlock(VAddr addr) {
- return *FindIterator(addr);
- }
-
-private:
- void MergeAdjacent(iterator it, iterator& next_it);
-
- [[maybe_unused]] const VAddr start_addr;
- [[maybe_unused]] const VAddr end_addr;
-
- MemoryBlockTree memory_block_tree;
-};
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/memory_layout.h b/src/core/hle/kernel/memory/memory_layout.h
deleted file mode 100644
index c7c0b2f49..000000000
--- a/src/core/hle/kernel/memory/memory_layout.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "common/common_types.h"
-#include "core/device_memory.h"
-
-namespace Kernel::Memory {
-
-constexpr std::size_t KernelAslrAlignment = 2 * 1024 * 1024;
-constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39;
-constexpr std::size_t KernelPhysicalAddressSpaceWidth = 1ULL << 48;
-constexpr std::size_t KernelVirtualAddressSpaceBase = 0ULL - KernelVirtualAddressSpaceWidth;
-constexpr std::size_t KernelVirtualAddressSpaceEnd =
- KernelVirtualAddressSpaceBase + (KernelVirtualAddressSpaceWidth - KernelAslrAlignment);
-constexpr std::size_t KernelVirtualAddressSpaceLast = KernelVirtualAddressSpaceEnd - 1;
-constexpr std::size_t KernelVirtualAddressSpaceSize =
- KernelVirtualAddressSpaceEnd - KernelVirtualAddressSpaceBase;
-
-constexpr bool IsKernelAddressKey(VAddr key) {
- return KernelVirtualAddressSpaceBase <= key && key <= KernelVirtualAddressSpaceLast;
-}
-
-constexpr bool IsKernelAddress(VAddr address) {
- return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd;
-}
-
-class MemoryRegion final {
- friend class MemoryLayout;
-
-public:
- constexpr PAddr StartAddress() const {
- return start_address;
- }
-
- constexpr PAddr EndAddress() const {
- return end_address;
- }
-
-private:
- constexpr MemoryRegion() = default;
- constexpr MemoryRegion(PAddr start_address, PAddr end_address)
- : start_address{start_address}, end_address{end_address} {}
-
- const PAddr start_address{};
- const PAddr end_address{};
-};
-
-class MemoryLayout final {
-public:
- constexpr const MemoryRegion& Application() const {
- return application;
- }
-
- constexpr const MemoryRegion& Applet() const {
- return applet;
- }
-
- constexpr const MemoryRegion& System() const {
- return system;
- }
-
- static constexpr MemoryLayout GetDefaultLayout() {
- constexpr std::size_t application_size{0xcd500000};
- constexpr std::size_t applet_size{0x1fb00000};
- constexpr PAddr application_start_address{Core::DramMemoryMap::End - application_size};
- constexpr PAddr application_end_address{Core::DramMemoryMap::End};
- constexpr PAddr applet_start_address{application_start_address - applet_size};
- constexpr PAddr applet_end_address{applet_start_address + applet_size};
- constexpr PAddr system_start_address{Core::DramMemoryMap::SlabHeapEnd};
- constexpr PAddr system_end_address{applet_start_address};
- return {application_start_address, application_end_address, applet_start_address,
- applet_end_address, system_start_address, system_end_address};
- }
-
-private:
- constexpr MemoryLayout(PAddr application_start_address, std::size_t application_size,
- PAddr applet_start_address, std::size_t applet_size,
- PAddr system_start_address, std::size_t system_size)
- : application{application_start_address, application_size},
- applet{applet_start_address, applet_size}, system{system_start_address, system_size} {}
-
- const MemoryRegion application;
- const MemoryRegion applet;
- const MemoryRegion system;
-};
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/memory_manager.cpp b/src/core/hle/kernel/memory/memory_manager.cpp
deleted file mode 100644
index 77f135cdc..000000000
--- a/src/core/hle/kernel/memory/memory_manager.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-
-#include "common/alignment.h"
-#include "common/assert.h"
-#include "common/common_types.h"
-#include "common/scope_exit.h"
-#include "core/hle/kernel/memory/memory_manager.h"
-#include "core/hle/kernel/memory/page_linked_list.h"
-#include "core/hle/kernel/svc_results.h"
-
-namespace Kernel::Memory {
-
-std::size_t MemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) {
- const auto size{end_address - start_address};
-
- // Calculate metadata sizes
- const auto ref_count_size{(size / PageSize) * sizeof(u16)};
- const auto optimize_map_size{(Common::AlignUp((size / PageSize), 64) / 64) * sizeof(u64)};
- const auto manager_size{Common::AlignUp(optimize_map_size + ref_count_size, PageSize)};
- const auto page_heap_size{PageHeap::CalculateMetadataOverheadSize(size)};
- const auto total_metadata_size{manager_size + page_heap_size};
- ASSERT(manager_size <= total_metadata_size);
- ASSERT(Common::IsAligned(total_metadata_size, PageSize));
-
- // Setup region
- pool = new_pool;
-
- // Initialize the manager's KPageHeap
- heap.Initialize(start_address, size, page_heap_size);
-
- // Free the memory to the heap
- heap.Free(start_address, size / PageSize);
-
- // Update the heap's used size
- heap.UpdateUsedSize();
-
- return total_metadata_size;
-}
-
-void MemoryManager::InitializeManager(Pool pool, u64 start_address, u64 end_address) {
- ASSERT(pool < Pool::Count);
- managers[static_cast<std::size_t>(pool)].Initialize(pool, start_address, end_address);
-}
-
-VAddr MemoryManager::AllocateContinuous(std::size_t num_pages, std::size_t align_pages, Pool pool,
- Direction dir) {
- // Early return if we're allocating no pages
- if (num_pages == 0) {
- return {};
- }
-
- // Lock the pool that we're allocating from
- const auto pool_index{static_cast<std::size_t>(pool)};
- std::lock_guard lock{pool_locks[pool_index]};
-
- // Choose a heap based on our page size request
- const s32 heap_index{PageHeap::GetAlignedBlockIndex(num_pages, align_pages)};
-
- // Loop, trying to iterate from each block
- // TODO (bunnei): Support multiple managers
- Impl& chosen_manager{managers[pool_index]};
- VAddr allocated_block{chosen_manager.AllocateBlock(heap_index)};
-
- // If we failed to allocate, quit now
- if (!allocated_block) {
- return {};
- }
-
- // If we allocated more than we need, free some
- const auto allocated_pages{PageHeap::GetBlockNumPages(heap_index)};
- if (allocated_pages > num_pages) {
- chosen_manager.Free(allocated_block + num_pages * PageSize, allocated_pages - num_pages);
- }
-
- return allocated_block;
-}
-
-ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pages, Pool pool,
- Direction dir) {
- ASSERT(page_list.GetNumPages() == 0);
-
- // Early return if we're allocating no pages
- if (num_pages == 0) {
- return RESULT_SUCCESS;
- }
-
- // Lock the pool that we're allocating from
- const auto pool_index{static_cast<std::size_t>(pool)};
- std::lock_guard lock{pool_locks[pool_index]};
-
- // Choose a heap based on our page size request
- const s32 heap_index{PageHeap::GetBlockIndex(num_pages)};
- if (heap_index < 0) {
- return ResultOutOfMemory;
- }
-
- // TODO (bunnei): Support multiple managers
- Impl& chosen_manager{managers[pool_index]};
-
- // Ensure that we don't leave anything un-freed
- auto group_guard = detail::ScopeExit([&] {
- for (const auto& it : page_list.Nodes()) {
- const auto min_num_pages{std::min<size_t>(
- it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)};
- chosen_manager.Free(it.GetAddress(), min_num_pages);
- }
- });
-
- // Keep allocating until we've allocated all our pages
- for (s32 index{heap_index}; index >= 0 && num_pages > 0; index--) {
- const auto pages_per_alloc{PageHeap::GetBlockNumPages(index)};
-
- while (num_pages >= pages_per_alloc) {
- // Allocate a block
- VAddr allocated_block{chosen_manager.AllocateBlock(index)};
- if (!allocated_block) {
- break;
- }
-
- // Safely add it to our group
- {
- auto block_guard = detail::ScopeExit(
- [&] { chosen_manager.Free(allocated_block, pages_per_alloc); });
-
- if (const ResultCode result{page_list.AddBlock(allocated_block, pages_per_alloc)};
- result.IsError()) {
- return result;
- }
-
- block_guard.Cancel();
- }
-
- num_pages -= pages_per_alloc;
- }
- }
-
- // Only succeed if we allocated as many pages as we wanted
- if (num_pages) {
- return ResultOutOfMemory;
- }
-
- // We succeeded!
- group_guard.Cancel();
- return RESULT_SUCCESS;
-}
-
-ResultCode MemoryManager::Free(PageLinkedList& page_list, std::size_t num_pages, Pool pool,
- Direction dir) {
- // Early return if we're freeing no pages
- if (!num_pages) {
- return RESULT_SUCCESS;
- }
-
- // Lock the pool that we're freeing from
- const auto pool_index{static_cast<std::size_t>(pool)};
- std::lock_guard lock{pool_locks[pool_index]};
-
- // TODO (bunnei): Support multiple managers
- Impl& chosen_manager{managers[pool_index]};
-
- // Free all of the pages
- for (const auto& it : page_list.Nodes()) {
- const auto min_num_pages{std::min<size_t>(
- it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)};
- chosen_manager.Free(it.GetAddress(), min_num_pages);
- }
-
- return RESULT_SUCCESS;
-}
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/memory_manager.h b/src/core/hle/kernel/memory/memory_manager.h
deleted file mode 100644
index 3cf444857..000000000
--- a/src/core/hle/kernel/memory/memory_manager.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-#include <mutex>
-
-#include "common/common_types.h"
-#include "core/hle/kernel/memory/page_heap.h"
-#include "core/hle/result.h"
-
-namespace Kernel::Memory {
-
-class PageLinkedList;
-
-class MemoryManager final : NonCopyable {
-public:
- enum class Pool : u32 {
- Application = 0,
- Applet = 1,
- System = 2,
- SystemNonSecure = 3,
-
- Count,
-
- Shift = 4,
- Mask = (0xF << Shift),
- };
-
- enum class Direction : u32 {
- FromFront = 0,
- FromBack = 1,
-
- Shift = 0,
- Mask = (0xF << Shift),
- };
-
- MemoryManager() = default;
-
- constexpr std::size_t GetSize(Pool pool) const {
- return managers[static_cast<std::size_t>(pool)].GetSize();
- }
-
- void InitializeManager(Pool pool, u64 start_address, u64 end_address);
- VAddr AllocateContinuous(std::size_t num_pages, std::size_t align_pages, Pool pool,
- Direction dir = Direction::FromFront);
- ResultCode Allocate(PageLinkedList& page_list, std::size_t num_pages, Pool pool,
- Direction dir = Direction::FromFront);
- ResultCode Free(PageLinkedList& page_list, std::size_t num_pages, Pool pool,
- Direction dir = Direction::FromFront);
-
- static constexpr std::size_t MaxManagerCount = 10;
-
-private:
- class Impl final : NonCopyable {
- private:
- using RefCount = u16;
-
- private:
- PageHeap heap;
- Pool pool{};
-
- public:
- Impl() = default;
-
- std::size_t Initialize(Pool new_pool, u64 start_address, u64 end_address);
-
- VAddr AllocateBlock(s32 index) {
- return heap.AllocateBlock(index);
- }
-
- void Free(VAddr addr, std::size_t num_pages) {
- heap.Free(addr, num_pages);
- }
-
- constexpr std::size_t GetSize() const {
- return heap.GetSize();
- }
-
- constexpr VAddr GetAddress() const {
- return heap.GetAddress();
- }
-
- constexpr VAddr GetEndAddress() const {
- return heap.GetEndAddress();
- }
- };
-
-private:
- std::array<std::mutex, static_cast<std::size_t>(Pool::Count)> pool_locks;
- std::array<Impl, MaxManagerCount> managers;
-};
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/memory_types.h b/src/core/hle/kernel/memory/memory_types.h
deleted file mode 100644
index a75bf77c0..000000000
--- a/src/core/hle/kernel/memory/memory_types.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-
-#include "common/common_types.h"
-
-namespace Kernel::Memory {
-
-constexpr std::size_t PageBits{12};
-constexpr std::size_t PageSize{1 << PageBits};
-
-using Page = std::array<u8, PageSize>;
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/page_heap.cpp b/src/core/hle/kernel/memory/page_heap.cpp
deleted file mode 100644
index 0ab1f7205..000000000
--- a/src/core/hle/kernel/memory/page_heap.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
-#include "core/core.h"
-#include "core/hle/kernel/memory/page_heap.h"
-#include "core/memory.h"
-
-namespace Kernel::Memory {
-
-void PageHeap::Initialize(VAddr address, std::size_t size, std::size_t metadata_size) {
- // Check our assumptions
- ASSERT(Common::IsAligned((address), PageSize));
- ASSERT(Common::IsAligned(size, PageSize));
-
- // Set our members
- heap_address = address;
- heap_size = size;
-
- // Setup bitmaps
- metadata.resize(metadata_size / sizeof(u64));
- u64* cur_bitmap_storage{metadata.data()};
- for (std::size_t i = 0; i < MemoryBlockPageShifts.size(); i++) {
- const std::size_t cur_block_shift{MemoryBlockPageShifts[i]};
- const std::size_t next_block_shift{
- (i != MemoryBlockPageShifts.size() - 1) ? MemoryBlockPageShifts[i + 1] : 0};
- cur_bitmap_storage = blocks[i].Initialize(heap_address, heap_size, cur_block_shift,
- next_block_shift, cur_bitmap_storage);
- }
-}
-
-VAddr PageHeap::AllocateBlock(s32 index) {
- const std::size_t needed_size{blocks[index].GetSize()};
-
- for (s32 i{index}; i < static_cast<s32>(MemoryBlockPageShifts.size()); i++) {
- if (const VAddr addr{blocks[i].PopBlock()}; addr) {
- if (const std::size_t allocated_size{blocks[i].GetSize()};
- allocated_size > needed_size) {
- Free(addr + needed_size, (allocated_size - needed_size) / PageSize);
- }
- return addr;
- }
- }
-
- return 0;
-}
-
-void PageHeap::FreeBlock(VAddr block, s32 index) {
- do {
- block = blocks[index++].PushBlock(block);
- } while (block != 0);
-}
-
-void PageHeap::Free(VAddr addr, std::size_t num_pages) {
- // Freeing no pages is a no-op
- if (num_pages == 0) {
- return;
- }
-
- // Find the largest block size that we can free, and free as many as possible
- s32 big_index{static_cast<s32>(MemoryBlockPageShifts.size()) - 1};
- const VAddr start{addr};
- const VAddr end{(num_pages * PageSize) + addr};
- VAddr before_start{start};
- VAddr before_end{start};
- VAddr after_start{end};
- VAddr after_end{end};
- while (big_index >= 0) {
- const std::size_t block_size{blocks[big_index].GetSize()};
- const VAddr big_start{Common::AlignUp((start), block_size)};
- const VAddr big_end{Common::AlignDown((end), block_size)};
- if (big_start < big_end) {
- // Free as many big blocks as we can
- for (auto block{big_start}; block < big_end; block += block_size) {
- FreeBlock(block, big_index);
- }
- before_end = big_start;
- after_start = big_end;
- break;
- }
- big_index--;
- }
- ASSERT(big_index >= 0);
-
- // Free space before the big blocks
- for (s32 i{big_index - 1}; i >= 0; i--) {
- const std::size_t block_size{blocks[i].GetSize()};
- while (before_start + block_size <= before_end) {
- before_end -= block_size;
- FreeBlock(before_end, i);
- }
- }
-
- // Free space after the big blocks
- for (s32 i{big_index - 1}; i >= 0; i--) {
- const std::size_t block_size{blocks[i].GetSize()};
- while (after_start + block_size <= after_end) {
- FreeBlock(after_start, i);
- after_start += block_size;
- }
- }
-}
-
-std::size_t PageHeap::CalculateMetadataOverheadSize(std::size_t region_size) {
- std::size_t overhead_size = 0;
- for (std::size_t i = 0; i < MemoryBlockPageShifts.size(); i++) {
- const std::size_t cur_block_shift{MemoryBlockPageShifts[i]};
- const std::size_t next_block_shift{
- (i != MemoryBlockPageShifts.size() - 1) ? MemoryBlockPageShifts[i + 1] : 0};
- overhead_size += PageHeap::Block::CalculateMetadataOverheadSize(
- region_size, cur_block_shift, next_block_shift);
- }
- return Common::AlignUp(overhead_size, PageSize);
-}
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/page_heap.h b/src/core/hle/kernel/memory/page_heap.h
deleted file mode 100644
index 131093284..000000000
--- a/src/core/hle/kernel/memory/page_heap.h
+++ /dev/null
@@ -1,370 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
-#pragma once
-
-#include <array>
-#include <bit>
-#include <vector>
-
-#include "common/alignment.h"
-#include "common/assert.h"
-#include "common/common_funcs.h"
-#include "common/common_types.h"
-#include "core/hle/kernel/memory/memory_types.h"
-
-namespace Kernel::Memory {
-
-class PageHeap final : NonCopyable {
-public:
- static constexpr s32 GetAlignedBlockIndex(std::size_t num_pages, std::size_t align_pages) {
- const auto target_pages{std::max(num_pages, align_pages)};
- for (std::size_t i = 0; i < NumMemoryBlockPageShifts; i++) {
- if (target_pages <=
- (static_cast<std::size_t>(1) << MemoryBlockPageShifts[i]) / PageSize) {
- return static_cast<s32>(i);
- }
- }
- return -1;
- }
-
- static constexpr s32 GetBlockIndex(std::size_t num_pages) {
- for (s32 i{static_cast<s32>(NumMemoryBlockPageShifts) - 1}; i >= 0; i--) {
- if (num_pages >= (static_cast<std::size_t>(1) << MemoryBlockPageShifts[i]) / PageSize) {
- return i;
- }
- }
- return -1;
- }
-
- static constexpr std::size_t GetBlockSize(std::size_t index) {
- return static_cast<std::size_t>(1) << MemoryBlockPageShifts[index];
- }
-
- static constexpr std::size_t GetBlockNumPages(std::size_t index) {
- return GetBlockSize(index) / PageSize;
- }
-
-private:
- static constexpr std::size_t NumMemoryBlockPageShifts{7};
- static constexpr std::array<std::size_t, NumMemoryBlockPageShifts> MemoryBlockPageShifts{
- 0xC, 0x10, 0x15, 0x16, 0x19, 0x1D, 0x1E,
- };
-
- class Block final : NonCopyable {
- private:
- class Bitmap final : NonCopyable {
- public:
- static constexpr std::size_t MaxDepth{4};
-
- private:
- std::array<u64*, MaxDepth> bit_storages{};
- std::size_t num_bits{};
- std::size_t used_depths{};
-
- public:
- constexpr Bitmap() = default;
-
- constexpr std::size_t GetNumBits() const {
- return num_bits;
- }
- constexpr s32 GetHighestDepthIndex() const {
- return static_cast<s32>(used_depths) - 1;
- }
-
- constexpr u64* Initialize(u64* storage, std::size_t size) {
- //* Initially, everything is un-set
- num_bits = 0;
-
- // Calculate the needed bitmap depth
- used_depths = static_cast<std::size_t>(GetRequiredDepth(size));
- ASSERT(used_depths <= MaxDepth);
-
- // Set the bitmap pointers
- for (s32 depth{GetHighestDepthIndex()}; depth >= 0; depth--) {
- bit_storages[depth] = storage;
- size = Common::AlignUp(size, 64) / 64;
- storage += size;
- }
-
- return storage;
- }
-
- s64 FindFreeBlock() const {
- uintptr_t offset{};
- s32 depth{};
-
- do {
- const u64 v{bit_storages[depth][offset]};
- if (v == 0) {
- // Non-zero depth indicates that a previous level had a free block
- ASSERT(depth == 0);
- return -1;
- }
- offset = offset * 64 + static_cast<u32>(std::countr_zero(v));
- ++depth;
- } while (depth < static_cast<s32>(used_depths));
-
- return static_cast<s64>(offset);
- }
-
- constexpr void SetBit(std::size_t offset) {
- SetBit(GetHighestDepthIndex(), offset);
- num_bits++;
- }
-
- constexpr void ClearBit(std::size_t offset) {
- ClearBit(GetHighestDepthIndex(), offset);
- num_bits--;
- }
-
- constexpr bool ClearRange(std::size_t offset, std::size_t count) {
- const s32 depth{GetHighestDepthIndex()};
- const auto bit_ind{offset / 64};
- u64* bits{bit_storages[depth]};
- if (count < 64) {
- const auto shift{offset % 64};
- ASSERT(shift + count <= 64);
- // Check that all the bits are set
- const u64 mask{((1ULL << count) - 1) << shift};
- u64 v{bits[bit_ind]};
- if ((v & mask) != mask) {
- return false;
- }
-
- // Clear the bits
- v &= ~mask;
- bits[bit_ind] = v;
- if (v == 0) {
- ClearBit(depth - 1, bit_ind);
- }
- } else {
- ASSERT(offset % 64 == 0);
- ASSERT(count % 64 == 0);
- // Check that all the bits are set
- std::size_t remaining{count};
- std::size_t i = 0;
- do {
- if (bits[bit_ind + i++] != ~u64(0)) {
- return false;
- }
- remaining -= 64;
- } while (remaining > 0);
-
- // Clear the bits
- remaining = count;
- i = 0;
- do {
- bits[bit_ind + i] = 0;
- ClearBit(depth - 1, bit_ind + i);
- i++;
- remaining -= 64;
- } while (remaining > 0);
- }
-
- num_bits -= count;
- return true;
- }
-
- private:
- constexpr void SetBit(s32 depth, std::size_t offset) {
- while (depth >= 0) {
- const auto ind{offset / 64};
- const auto which{offset % 64};
- const u64 mask{1ULL << which};
-
- u64* bit{std::addressof(bit_storages[depth][ind])};
- const u64 v{*bit};
- ASSERT((v & mask) == 0);
- *bit = v | mask;
- if (v) {
- break;
- }
- offset = ind;
- depth--;
- }
- }
-
- constexpr void ClearBit(s32 depth, std::size_t offset) {
- while (depth >= 0) {
- const auto ind{offset / 64};
- const auto which{offset % 64};
- const u64 mask{1ULL << which};
-
- u64* bit{std::addressof(bit_storages[depth][ind])};
- u64 v{*bit};
- ASSERT((v & mask) != 0);
- v &= ~mask;
- *bit = v;
- if (v) {
- break;
- }
- offset = ind;
- depth--;
- }
- }
-
- private:
- static constexpr s32 GetRequiredDepth(std::size_t region_size) {
- s32 depth = 0;
- while (true) {
- region_size /= 64;
- depth++;
- if (region_size == 0) {
- return depth;
- }
- }
- }
-
- public:
- static constexpr std::size_t CalculateMetadataOverheadSize(std::size_t region_size) {
- std::size_t overhead_bits = 0;
- for (s32 depth{GetRequiredDepth(region_size) - 1}; depth >= 0; depth--) {
- region_size = Common::AlignUp(region_size, 64) / 64;
- overhead_bits += region_size;
- }
- return overhead_bits * sizeof(u64);
- }
- };
-
- private:
- Bitmap bitmap;
- VAddr heap_address{};
- uintptr_t end_offset{};
- std::size_t block_shift{};
- std::size_t next_block_shift{};
-
- public:
- constexpr Block() = default;
-
- constexpr std::size_t GetShift() const {
- return block_shift;
- }
- constexpr std::size_t GetNextShift() const {
- return next_block_shift;
- }
- constexpr std::size_t GetSize() const {
- return static_cast<std::size_t>(1) << GetShift();
- }
- constexpr std::size_t GetNumPages() const {
- return GetSize() / PageSize;
- }
- constexpr std::size_t GetNumFreeBlocks() const {
- return bitmap.GetNumBits();
- }
- constexpr std::size_t GetNumFreePages() const {
- return GetNumFreeBlocks() * GetNumPages();
- }
-
- constexpr u64* Initialize(VAddr addr, std::size_t size, std::size_t bs, std::size_t nbs,
- u64* bit_storage) {
- // Set shifts
- block_shift = bs;
- next_block_shift = nbs;
-
- // Align up the address
- VAddr end{addr + size};
- const auto align{(next_block_shift != 0) ? (1ULL << next_block_shift)
- : (1ULL << block_shift)};
- addr = Common::AlignDown((addr), align);
- end = Common::AlignUp((end), align);
-
- heap_address = addr;
- end_offset = (end - addr) / (1ULL << block_shift);
- return bitmap.Initialize(bit_storage, end_offset);
- }
-
- constexpr VAddr PushBlock(VAddr address) {
- // Set the bit for the free block
- std::size_t offset{(address - heap_address) >> GetShift()};
- bitmap.SetBit(offset);
-
- // If we have a next shift, try to clear the blocks below and return the address
- if (GetNextShift()) {
- const auto diff{1ULL << (GetNextShift() - GetShift())};
- offset = Common::AlignDown(offset, diff);
- if (bitmap.ClearRange(offset, diff)) {
- return heap_address + (offset << GetShift());
- }
- }
-
- // We couldn't coalesce, or we're already as big as possible
- return 0;
- }
-
- VAddr PopBlock() {
- // Find a free block
- const s64 soffset{bitmap.FindFreeBlock()};
- if (soffset < 0) {
- return 0;
- }
- const auto offset{static_cast<std::size_t>(soffset)};
-
- // Update our tracking and return it
- bitmap.ClearBit(offset);
- return heap_address + (offset << GetShift());
- }
-
- public:
- static constexpr std::size_t CalculateMetadataOverheadSize(std::size_t region_size,
- std::size_t cur_block_shift,
- std::size_t next_block_shift) {
- const auto cur_block_size{(1ULL << cur_block_shift)};
- const auto next_block_size{(1ULL << next_block_shift)};
- const auto align{(next_block_shift != 0) ? next_block_size : cur_block_size};
- return Bitmap::CalculateMetadataOverheadSize(
- (align * 2 + Common::AlignUp(region_size, align)) / cur_block_size);
- }
- };
-
-public:
- PageHeap() = default;
-
- constexpr VAddr GetAddress() const {
- return heap_address;
- }
- constexpr std::size_t GetSize() const {
- return heap_size;
- }
- constexpr VAddr GetEndAddress() const {
- return GetAddress() + GetSize();
- }
- constexpr std::size_t GetPageOffset(VAddr block) const {
- return (block - GetAddress()) / PageSize;
- }
-
- void Initialize(VAddr heap_address, std::size_t heap_size, std::size_t metadata_size);
- VAddr AllocateBlock(s32 index);
- void Free(VAddr addr, std::size_t num_pages);
-
- void UpdateUsedSize() {
- used_size = heap_size - (GetNumFreePages() * PageSize);
- }
-
- static std::size_t CalculateMetadataOverheadSize(std::size_t region_size);
-
-private:
- constexpr std::size_t GetNumFreePages() const {
- std::size_t num_free{};
-
- for (const auto& block : blocks) {
- num_free += block.GetNumFreePages();
- }
-
- return num_free;
- }
-
- void FreeBlock(VAddr block, s32 index);
-
- VAddr heap_address{};
- std::size_t heap_size{};
- std::size_t used_size{};
- std::array<Block, NumMemoryBlockPageShifts> blocks{};
- std::vector<u64> metadata;
-};
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/page_linked_list.h b/src/core/hle/kernel/memory/page_linked_list.h
deleted file mode 100644
index 45dc13eaf..000000000
--- a/src/core/hle/kernel/memory/page_linked_list.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <list>
-
-#include "common/assert.h"
-#include "common/common_types.h"
-#include "core/hle/kernel/memory/memory_types.h"
-#include "core/hle/result.h"
-
-namespace Kernel::Memory {
-
-class PageLinkedList final {
-public:
- class Node final {
- public:
- constexpr Node(u64 addr, std::size_t num_pages) : addr{addr}, num_pages{num_pages} {}
-
- constexpr u64 GetAddress() const {
- return addr;
- }
-
- constexpr std::size_t GetNumPages() const {
- return num_pages;
- }
-
- private:
- u64 addr{};
- std::size_t num_pages{};
- };
-
-public:
- PageLinkedList() = default;
- PageLinkedList(u64 address, u64 num_pages) {
- ASSERT(AddBlock(address, num_pages).IsSuccess());
- }
-
- constexpr std::list<Node>& Nodes() {
- return nodes;
- }
-
- constexpr const std::list<Node>& Nodes() const {
- return nodes;
- }
-
- std::size_t GetNumPages() const {
- std::size_t num_pages = 0;
- for (const Node& node : nodes) {
- num_pages += node.GetNumPages();
- }
- return num_pages;
- }
-
- bool IsEqual(PageLinkedList& other) const {
- auto this_node = nodes.begin();
- auto other_node = other.nodes.begin();
- while (this_node != nodes.end() && other_node != other.nodes.end()) {
- if (this_node->GetAddress() != other_node->GetAddress() ||
- this_node->GetNumPages() != other_node->GetNumPages()) {
- return false;
- }
- this_node = std::next(this_node);
- other_node = std::next(other_node);
- }
-
- return this_node == nodes.end() && other_node == other.nodes.end();
- }
-
- ResultCode AddBlock(u64 address, u64 num_pages) {
- if (!num_pages) {
- return RESULT_SUCCESS;
- }
- if (!nodes.empty()) {
- const auto node = nodes.back();
- if (node.GetAddress() + node.GetNumPages() * PageSize == address) {
- address = node.GetAddress();
- num_pages += node.GetNumPages();
- nodes.pop_back();
- }
- }
- nodes.push_back({address, num_pages});
- return RESULT_SUCCESS;
- }
-
-private:
- std::list<Node> nodes;
-};
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp
deleted file mode 100644
index 00ed9b881..000000000
--- a/src/core/hle/kernel/memory/page_table.cpp
+++ /dev/null
@@ -1,1184 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "common/alignment.h"
-#include "common/assert.h"
-#include "common/scope_exit.h"
-#include "core/core.h"
-#include "core/hle/kernel/k_scoped_resource_reservation.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/memory/address_space_info.h"
-#include "core/hle/kernel/memory/memory_block.h"
-#include "core/hle/kernel/memory/memory_block_manager.h"
-#include "core/hle/kernel/memory/page_linked_list.h"
-#include "core/hle/kernel/memory/page_table.h"
-#include "core/hle/kernel/memory/system_control.h"
-#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/svc_results.h"
-#include "core/memory.h"
-
-namespace Kernel::Memory {
-
-namespace {
-
-constexpr std::size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceType as_type) {
- switch (as_type) {
- case FileSys::ProgramAddressSpaceType::Is32Bit:
- case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
- return 32;
- case FileSys::ProgramAddressSpaceType::Is36Bit:
- return 36;
- case FileSys::ProgramAddressSpaceType::Is39Bit:
- return 39;
- default:
- UNREACHABLE();
- return {};
- }
-}
-
-constexpr u64 GetAddressInRange(const MemoryInfo& info, VAddr addr) {
- if (info.GetAddress() < addr) {
- return addr;
- }
- return info.GetAddress();
-}
-
-constexpr std::size_t GetSizeInRange(const MemoryInfo& info, VAddr start, VAddr end) {
- std::size_t size{info.GetSize()};
- if (info.GetAddress() < start) {
- size -= start - info.GetAddress();
- }
- if (info.GetEndAddress() > end) {
- size -= info.GetEndAddress() - end;
- }
- return size;
-}
-
-} // namespace
-
-PageTable::PageTable(Core::System& system) : system{system} {}
-
-ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type,
- bool enable_aslr, VAddr code_addr, std::size_t code_size,
- Memory::MemoryManager::Pool pool) {
-
- const auto GetSpaceStart = [this](AddressSpaceInfo::Type type) {
- return AddressSpaceInfo::GetAddressSpaceStart(address_space_width, type);
- };
- const auto GetSpaceSize = [this](AddressSpaceInfo::Type type) {
- return AddressSpaceInfo::GetAddressSpaceSize(address_space_width, type);
- };
-
- // Set our width and heap/alias sizes
- address_space_width = GetAddressSpaceWidthFromType(as_type);
- const VAddr start = 0;
- const VAddr end{1ULL << address_space_width};
- std::size_t alias_region_size{GetSpaceSize(AddressSpaceInfo::Type::Alias)};
- std::size_t heap_region_size{GetSpaceSize(AddressSpaceInfo::Type::Heap)};
-
- ASSERT(start <= code_addr);
- ASSERT(code_addr < code_addr + code_size);
- ASSERT(code_addr + code_size - 1 <= end - 1);
-
- // Adjust heap/alias size if we don't have an alias region
- if (as_type == FileSys::ProgramAddressSpaceType::Is32BitNoMap) {
- heap_region_size += alias_region_size;
- alias_region_size = 0;
- }
-
- // Set code regions and determine remaining
- constexpr std::size_t RegionAlignment{2 * 1024 * 1024};
- VAddr process_code_start{};
- VAddr process_code_end{};
- std::size_t stack_region_size{};
- std::size_t kernel_map_region_size{};
-
- if (address_space_width == 39) {
- alias_region_size = GetSpaceSize(AddressSpaceInfo::Type::Alias);
- heap_region_size = GetSpaceSize(AddressSpaceInfo::Type::Heap);
- stack_region_size = GetSpaceSize(AddressSpaceInfo::Type::Stack);
- kernel_map_region_size = GetSpaceSize(AddressSpaceInfo::Type::Is32Bit);
- code_region_start = GetSpaceStart(AddressSpaceInfo::Type::Large64Bit);
- code_region_end = code_region_start + GetSpaceSize(AddressSpaceInfo::Type::Large64Bit);
- alias_code_region_start = code_region_start;
- alias_code_region_end = code_region_end;
- process_code_start = Common::AlignDown(code_addr, RegionAlignment);
- process_code_end = Common::AlignUp(code_addr + code_size, RegionAlignment);
- } else {
- stack_region_size = 0;
- kernel_map_region_size = 0;
- code_region_start = GetSpaceStart(AddressSpaceInfo::Type::Is32Bit);
- code_region_end = code_region_start + GetSpaceSize(AddressSpaceInfo::Type::Is32Bit);
- stack_region_start = code_region_start;
- alias_code_region_start = code_region_start;
- alias_code_region_end = GetSpaceStart(AddressSpaceInfo::Type::Small64Bit) +
- GetSpaceSize(AddressSpaceInfo::Type::Small64Bit);
- stack_region_end = code_region_end;
- kernel_map_region_start = code_region_start;
- kernel_map_region_end = code_region_end;
- process_code_start = code_region_start;
- process_code_end = code_region_end;
- }
-
- // Set other basic fields
- is_aslr_enabled = enable_aslr;
- address_space_start = start;
- address_space_end = end;
- is_kernel = false;
-
- // Determine the region we can place our undetermineds in
- VAddr alloc_start{};
- std::size_t alloc_size{};
- if ((process_code_start - code_region_start) >= (end - process_code_end)) {
- alloc_start = code_region_start;
- alloc_size = process_code_start - code_region_start;
- } else {
- alloc_start = process_code_end;
- alloc_size = end - process_code_end;
- }
- const std::size_t needed_size{
- (alias_region_size + heap_region_size + stack_region_size + kernel_map_region_size)};
- if (alloc_size < needed_size) {
- UNREACHABLE();
- return ResultOutOfMemory;
- }
-
- const std::size_t remaining_size{alloc_size - needed_size};
-
- // Determine random placements for each region
- std::size_t alias_rnd{}, heap_rnd{}, stack_rnd{}, kmap_rnd{};
- if (enable_aslr) {
- alias_rnd = SystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) *
- RegionAlignment;
- heap_rnd = SystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) *
- RegionAlignment;
- stack_rnd = SystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) *
- RegionAlignment;
- kmap_rnd = SystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) *
- RegionAlignment;
- }
-
- // Setup heap and alias regions
- alias_region_start = alloc_start + alias_rnd;
- alias_region_end = alias_region_start + alias_region_size;
- heap_region_start = alloc_start + heap_rnd;
- heap_region_end = heap_region_start + heap_region_size;
-
- if (alias_rnd <= heap_rnd) {
- heap_region_start += alias_region_size;
- heap_region_end += alias_region_size;
- } else {
- alias_region_start += heap_region_size;
- alias_region_end += heap_region_size;
- }
-
- // Setup stack region
- if (stack_region_size) {
- stack_region_start = alloc_start + stack_rnd;
- stack_region_end = stack_region_start + stack_region_size;
-
- if (alias_rnd < stack_rnd) {
- stack_region_start += alias_region_size;
- stack_region_end += alias_region_size;
- } else {
- alias_region_start += stack_region_size;
- alias_region_end += stack_region_size;
- }
-
- if (heap_rnd < stack_rnd) {
- stack_region_start += heap_region_size;
- stack_region_end += heap_region_size;
- } else {
- heap_region_start += stack_region_size;
- heap_region_end += stack_region_size;
- }
- }
-
- // Setup kernel map region
- if (kernel_map_region_size) {
- kernel_map_region_start = alloc_start + kmap_rnd;
- kernel_map_region_end = kernel_map_region_start + kernel_map_region_size;
-
- if (alias_rnd < kmap_rnd) {
- kernel_map_region_start += alias_region_size;
- kernel_map_region_end += alias_region_size;
- } else {
- alias_region_start += kernel_map_region_size;
- alias_region_end += kernel_map_region_size;
- }
-
- if (heap_rnd < kmap_rnd) {
- kernel_map_region_start += heap_region_size;
- kernel_map_region_end += heap_region_size;
- } else {
- heap_region_start += kernel_map_region_size;
- heap_region_end += kernel_map_region_size;
- }
-
- if (stack_region_size) {
- if (stack_rnd < kmap_rnd) {
- kernel_map_region_start += stack_region_size;
- kernel_map_region_end += stack_region_size;
- } else {
- stack_region_start += kernel_map_region_size;
- stack_region_end += kernel_map_region_size;
- }
- }
- }
-
- // Set heap members
- current_heap_end = heap_region_start;
- max_heap_size = 0;
- max_physical_memory_size = 0;
-
- // Ensure that we regions inside our address space
- auto IsInAddressSpace = [&](VAddr addr) {
- return address_space_start <= addr && addr <= address_space_end;
- };
- ASSERT(IsInAddressSpace(alias_region_start));
- ASSERT(IsInAddressSpace(alias_region_end));
- ASSERT(IsInAddressSpace(heap_region_start));
- ASSERT(IsInAddressSpace(heap_region_end));
- ASSERT(IsInAddressSpace(stack_region_start));
- ASSERT(IsInAddressSpace(stack_region_end));
- ASSERT(IsInAddressSpace(kernel_map_region_start));
- ASSERT(IsInAddressSpace(kernel_map_region_end));
-
- // Ensure that we selected regions that don't overlap
- const VAddr alias_start{alias_region_start};
- const VAddr alias_last{alias_region_end - 1};
- const VAddr heap_start{heap_region_start};
- const VAddr heap_last{heap_region_end - 1};
- const VAddr stack_start{stack_region_start};
- const VAddr stack_last{stack_region_end - 1};
- const VAddr kmap_start{kernel_map_region_start};
- const VAddr kmap_last{kernel_map_region_end - 1};
- ASSERT(alias_last < heap_start || heap_last < alias_start);
- ASSERT(alias_last < stack_start || stack_last < alias_start);
- ASSERT(alias_last < kmap_start || kmap_last < alias_start);
- ASSERT(heap_last < stack_start || stack_last < heap_start);
- ASSERT(heap_last < kmap_start || kmap_last < heap_start);
-
- current_heap_addr = heap_region_start;
- heap_capacity = 0;
- physical_memory_usage = 0;
- memory_pool = pool;
-
- page_table_impl.Resize(address_space_width, PageBits);
-
- return InitializeMemoryLayout(start, end);
-}
-
-ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemoryState state,
- MemoryPermission perm) {
- std::lock_guard lock{page_table_lock};
-
- const u64 size{num_pages * PageSize};
-
- if (!CanContain(addr, size, state)) {
- return ResultInvalidCurrentMemory;
- }
-
- if (IsRegionMapped(addr, size)) {
- return ResultInvalidCurrentMemory;
- }
-
- PageLinkedList page_linked_list;
- CASCADE_CODE(
- system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool));
- CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup));
-
- block_manager->Update(addr, num_pages, state, perm);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- const std::size_t num_pages{size / PageSize};
-
- MemoryState state{};
- MemoryPermission perm{};
- CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, MemoryState::All,
- MemoryState::Normal, MemoryPermission::Mask,
- MemoryPermission::ReadAndWrite, MemoryAttribute::Mask,
- MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
-
- if (IsRegionMapped(dst_addr, size)) {
- return ResultInvalidCurrentMemory;
- }
-
- PageLinkedList page_linked_list;
- AddRegionToPages(src_addr, num_pages, page_linked_list);
-
- {
- auto block_guard = detail::ScopeExit(
- [&] { Operate(src_addr, num_pages, perm, OperationType::ChangePermissions); });
-
- CASCADE_CODE(
- Operate(src_addr, num_pages, MemoryPermission::None, OperationType::ChangePermissions));
- CASCADE_CODE(MapPages(dst_addr, page_linked_list, MemoryPermission::None));
-
- block_guard.Cancel();
- }
-
- block_manager->Update(src_addr, num_pages, state, MemoryPermission::None,
- MemoryAttribute::Locked);
- block_manager->Update(dst_addr, num_pages, MemoryState::AliasCode);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- if (!size) {
- return RESULT_SUCCESS;
- }
-
- const std::size_t num_pages{size / PageSize};
-
- CASCADE_CODE(CheckMemoryState(nullptr, nullptr, nullptr, src_addr, size, MemoryState::All,
- MemoryState::Normal, MemoryPermission::None,
- MemoryPermission::None, MemoryAttribute::Mask,
- MemoryAttribute::Locked, MemoryAttribute::IpcAndDeviceMapped));
-
- MemoryState state{};
- CASCADE_CODE(CheckMemoryState(
- &state, nullptr, nullptr, dst_addr, PageSize, MemoryState::FlagCanCodeAlias,
- MemoryState::FlagCanCodeAlias, MemoryPermission::None, MemoryPermission::None,
- MemoryAttribute::Mask, MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
- CASCADE_CODE(CheckMemoryState(dst_addr, size, MemoryState::All, state, MemoryPermission::None,
- MemoryPermission::None, MemoryAttribute::Mask,
- MemoryAttribute::None));
- CASCADE_CODE(Operate(dst_addr, num_pages, MemoryPermission::None, OperationType::Unmap));
-
- block_manager->Update(dst_addr, num_pages, MemoryState::Free);
- block_manager->Update(src_addr, num_pages, MemoryState::Normal, MemoryPermission::ReadAndWrite);
-
- return RESULT_SUCCESS;
-}
-
-void PageTable::MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, VAddr end) {
- auto node{page_linked_list.Nodes().begin()};
- PAddr map_addr{node->GetAddress()};
- std::size_t src_num_pages{node->GetNumPages()};
-
- block_manager->IterateForRange(start, end, [&](const MemoryInfo& info) {
- if (info.state != MemoryState::Free) {
- return;
- }
-
- std::size_t dst_num_pages{GetSizeInRange(info, start, end) / PageSize};
- VAddr dst_addr{GetAddressInRange(info, start)};
-
- while (dst_num_pages) {
- if (!src_num_pages) {
- node = std::next(node);
- map_addr = node->GetAddress();
- src_num_pages = node->GetNumPages();
- }
-
- const std::size_t num_pages{std::min(src_num_pages, dst_num_pages)};
- Operate(dst_addr, num_pages, MemoryPermission::ReadAndWrite, OperationType::Map,
- map_addr);
-
- dst_addr += num_pages * PageSize;
- map_addr += num_pages * PageSize;
- src_num_pages -= num_pages;
- dst_num_pages -= num_pages;
- }
- });
-}
-
-ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- std::size_t mapped_size{};
- const VAddr end_addr{addr + size};
-
- block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) {
- if (info.state != MemoryState::Free) {
- mapped_size += GetSizeInRange(info, addr, end_addr);
- }
- });
-
- if (mapped_size == size) {
- return RESULT_SUCCESS;
- }
-
- const std::size_t remaining_size{size - mapped_size};
- const std::size_t remaining_pages{remaining_size / PageSize};
-
- // Reserve the memory from the process resource limit.
- KScopedResourceReservation memory_reservation(
- system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory,
- remaining_size);
- if (!memory_reservation.Succeeded()) {
- LOG_ERROR(Kernel, "Could not reserve remaining {:X} bytes", remaining_size);
- return ResultResourceLimitedExceeded;
- }
-
- PageLinkedList page_linked_list;
-
- CASCADE_CODE(
- system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, memory_pool));
-
- // We succeeded, so commit the memory reservation.
- memory_reservation.Commit();
-
- MapPhysicalMemory(page_linked_list, addr, end_addr);
-
- physical_memory_usage += remaining_size;
-
- const std::size_t num_pages{size / PageSize};
- block_manager->Update(addr, num_pages, MemoryState::Free, MemoryPermission::None,
- MemoryAttribute::None, MemoryState::Normal,
- MemoryPermission::ReadAndWrite, MemoryAttribute::None);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- const VAddr end_addr{addr + size};
- ResultCode result{RESULT_SUCCESS};
- std::size_t mapped_size{};
-
- // Verify that the region can be unmapped
- block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) {
- if (info.state == MemoryState::Normal) {
- if (info.attribute != MemoryAttribute::None) {
- result = ResultInvalidCurrentMemory;
- return;
- }
- mapped_size += GetSizeInRange(info, addr, end_addr);
- } else if (info.state != MemoryState::Free) {
- result = ResultInvalidCurrentMemory;
- }
- });
-
- if (result.IsError()) {
- return result;
- }
-
- if (!mapped_size) {
- return RESULT_SUCCESS;
- }
-
- CASCADE_CODE(UnmapMemory(addr, size));
-
- auto process{system.Kernel().CurrentProcess()};
- process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size);
- physical_memory_usage -= mapped_size;
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- const VAddr end_addr{addr + size};
- ResultCode result{RESULT_SUCCESS};
- PageLinkedList page_linked_list;
-
- // Unmap each region within the range
- block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) {
- if (info.state == MemoryState::Normal) {
- const std::size_t block_size{GetSizeInRange(info, addr, end_addr)};
- const std::size_t block_num_pages{block_size / PageSize};
- const VAddr block_addr{GetAddressInRange(info, addr)};
-
- AddRegionToPages(block_addr, block_size / PageSize, page_linked_list);
-
- if (result = Operate(block_addr, block_num_pages, MemoryPermission::None,
- OperationType::Unmap);
- result.IsError()) {
- return;
- }
- }
- });
-
- if (result.IsError()) {
- return result;
- }
-
- const std::size_t num_pages{size / PageSize};
- system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool);
-
- block_manager->Update(addr, num_pages, MemoryState::Free);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- MemoryState src_state{};
- CASCADE_CODE(CheckMemoryState(
- &src_state, nullptr, nullptr, src_addr, size, MemoryState::FlagCanAlias,
- MemoryState::FlagCanAlias, MemoryPermission::Mask, MemoryPermission::ReadAndWrite,
- MemoryAttribute::Mask, MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
-
- if (IsRegionMapped(dst_addr, size)) {
- return ResultInvalidCurrentMemory;
- }
-
- PageLinkedList page_linked_list;
- const std::size_t num_pages{size / PageSize};
-
- AddRegionToPages(src_addr, num_pages, page_linked_list);
-
- {
- auto block_guard = detail::ScopeExit([&] {
- Operate(src_addr, num_pages, MemoryPermission::ReadAndWrite,
- OperationType::ChangePermissions);
- });
-
- CASCADE_CODE(
- Operate(src_addr, num_pages, MemoryPermission::None, OperationType::ChangePermissions));
- CASCADE_CODE(MapPages(dst_addr, page_linked_list, MemoryPermission::ReadAndWrite));
-
- block_guard.Cancel();
- }
-
- block_manager->Update(src_addr, num_pages, src_state, MemoryPermission::None,
- MemoryAttribute::Locked);
- block_manager->Update(dst_addr, num_pages, MemoryState::Stack, MemoryPermission::ReadAndWrite);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- MemoryState src_state{};
- CASCADE_CODE(CheckMemoryState(
- &src_state, nullptr, nullptr, src_addr, size, MemoryState::FlagCanAlias,
- MemoryState::FlagCanAlias, MemoryPermission::Mask, MemoryPermission::None,
- MemoryAttribute::Mask, MemoryAttribute::Locked, MemoryAttribute::IpcAndDeviceMapped));
-
- MemoryPermission dst_perm{};
- CASCADE_CODE(CheckMemoryState(nullptr, &dst_perm, nullptr, dst_addr, size, MemoryState::All,
- MemoryState::Stack, MemoryPermission::None,
- MemoryPermission::None, MemoryAttribute::Mask,
- MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
-
- PageLinkedList src_pages;
- PageLinkedList dst_pages;
- const std::size_t num_pages{size / PageSize};
-
- AddRegionToPages(src_addr, num_pages, src_pages);
- AddRegionToPages(dst_addr, num_pages, dst_pages);
-
- if (!dst_pages.IsEqual(src_pages)) {
- return ResultInvalidMemoryRange;
- }
-
- {
- auto block_guard = detail::ScopeExit([&] { MapPages(dst_addr, dst_pages, dst_perm); });
-
- CASCADE_CODE(Operate(dst_addr, num_pages, MemoryPermission::None, OperationType::Unmap));
- CASCADE_CODE(Operate(src_addr, num_pages, MemoryPermission::ReadAndWrite,
- OperationType::ChangePermissions));
-
- block_guard.Cancel();
- }
-
- block_manager->Update(src_addr, num_pages, src_state, MemoryPermission::ReadAndWrite);
- block_manager->Update(dst_addr, num_pages, MemoryState::Free);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_list,
- MemoryPermission perm) {
- VAddr cur_addr{addr};
-
- for (const auto& node : page_linked_list.Nodes()) {
- if (const auto result{
- Operate(cur_addr, node.GetNumPages(), perm, OperationType::Map, node.GetAddress())};
- result.IsError()) {
- const std::size_t num_pages{(addr - cur_addr) / PageSize};
-
- ASSERT(
- Operate(addr, num_pages, MemoryPermission::None, OperationType::Unmap).IsSuccess());
-
- return result;
- }
-
- cur_addr += node.GetNumPages() * PageSize;
- }
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state,
- MemoryPermission perm) {
- std::lock_guard lock{page_table_lock};
-
- const std::size_t num_pages{page_linked_list.GetNumPages()};
- const std::size_t size{num_pages * PageSize};
-
- if (!CanContain(addr, size, state)) {
- return ResultInvalidCurrentMemory;
- }
-
- if (IsRegionMapped(addr, num_pages * PageSize)) {
- return ResultInvalidCurrentMemory;
- }
-
- CASCADE_CODE(MapPages(addr, page_linked_list, perm));
-
- block_manager->Update(addr, num_pages, state, perm);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm) {
-
- std::lock_guard lock{page_table_lock};
-
- MemoryState prev_state{};
- MemoryPermission prev_perm{};
-
- CASCADE_CODE(CheckMemoryState(
- &prev_state, &prev_perm, nullptr, addr, size, MemoryState::FlagCode, MemoryState::FlagCode,
- MemoryPermission::None, MemoryPermission::None, MemoryAttribute::Mask,
- MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
-
- MemoryState state{prev_state};
-
- // Ensure state is mutable if permission allows write
- if ((perm & MemoryPermission::Write) != MemoryPermission::None) {
- if (prev_state == MemoryState::Code) {
- state = MemoryState::CodeData;
- } else if (prev_state == MemoryState::AliasCode) {
- state = MemoryState::AliasCodeData;
- } else {
- UNREACHABLE();
- }
- }
-
- // Return early if there is nothing to change
- if (state == prev_state && perm == prev_perm) {
- return RESULT_SUCCESS;
- }
-
- if ((prev_perm & MemoryPermission::Execute) != (perm & MemoryPermission::Execute)) {
- // Memory execution state is changing, invalidate CPU cache range
- system.InvalidateCpuInstructionCacheRange(addr, size);
- }
-
- const std::size_t num_pages{size / PageSize};
- const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None
- ? OperationType::ChangePermissionsAndRefresh
- : OperationType::ChangePermissions};
-
- CASCADE_CODE(Operate(addr, num_pages, perm, operation));
-
- block_manager->Update(addr, num_pages, state, perm);
-
- return RESULT_SUCCESS;
-}
-
-MemoryInfo PageTable::QueryInfoImpl(VAddr addr) {
- std::lock_guard lock{page_table_lock};
-
- return block_manager->FindBlock(addr).GetMemoryInfo();
-}
-
-MemoryInfo PageTable::QueryInfo(VAddr addr) {
- if (!Contains(addr, 1)) {
- return {address_space_end, 0 - address_space_end, MemoryState::Inaccessible,
- MemoryPermission::None, MemoryAttribute::None, MemoryPermission::None};
- }
-
- return QueryInfoImpl(addr);
-}
-
-ResultCode PageTable::ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm) {
- std::lock_guard lock{page_table_lock};
-
- MemoryState state{};
- MemoryAttribute attribute{};
-
- CASCADE_CODE(CheckMemoryState(&state, nullptr, &attribute, addr, size,
- MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted,
- MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted,
- MemoryPermission::Mask, MemoryPermission::ReadAndWrite,
- MemoryAttribute::Mask, MemoryAttribute::None,
- MemoryAttribute::IpcAndDeviceMapped));
-
- block_manager->Update(addr, size / PageSize, state, perm, attribute | MemoryAttribute::Locked);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- MemoryState state{};
-
- CASCADE_CODE(CheckMemoryState(&state, nullptr, nullptr, addr, size,
- MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted,
- MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted,
- MemoryPermission::None, MemoryPermission::None,
- MemoryAttribute::Mask, MemoryAttribute::Locked,
- MemoryAttribute::IpcAndDeviceMapped));
-
- block_manager->Update(addr, size / PageSize, state, MemoryPermission::ReadAndWrite);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask,
- MemoryAttribute value) {
- std::lock_guard lock{page_table_lock};
-
- MemoryState state{};
- MemoryPermission perm{};
- MemoryAttribute attribute{};
-
- CASCADE_CODE(CheckMemoryState(&state, &perm, &attribute, addr, size,
- MemoryState::FlagCanChangeAttribute,
- MemoryState::FlagCanChangeAttribute, MemoryPermission::None,
- MemoryPermission::None, MemoryAttribute::LockedAndIpcLocked,
- MemoryAttribute::None, MemoryAttribute::DeviceSharedAndUncached));
-
- attribute = attribute & ~mask;
- attribute = attribute | (mask & value);
-
- block_manager->Update(addr, size / PageSize, state, perm, attribute);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::SetHeapCapacity(std::size_t new_heap_capacity) {
- std::lock_guard lock{page_table_lock};
- heap_capacity = new_heap_capacity;
- return RESULT_SUCCESS;
-}
-
-ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
-
- if (size > heap_region_end - heap_region_start) {
- return ResultOutOfMemory;
- }
-
- const u64 previous_heap_size{GetHeapSize()};
-
- UNIMPLEMENTED_IF_MSG(previous_heap_size > size, "Heap shrink is unimplemented");
-
- // Increase the heap size
- {
- std::lock_guard lock{page_table_lock};
-
- const u64 delta{size - previous_heap_size};
-
- // Reserve memory for the heap extension.
- KScopedResourceReservation memory_reservation(
- system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory,
- delta);
-
- if (!memory_reservation.Succeeded()) {
- LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta);
- return ResultResourceLimitedExceeded;
- }
-
- PageLinkedList page_linked_list;
- const std::size_t num_pages{delta / PageSize};
-
- CASCADE_CODE(
- system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool));
-
- if (IsRegionMapped(current_heap_addr, delta)) {
- return ResultInvalidCurrentMemory;
- }
-
- CASCADE_CODE(
- Operate(current_heap_addr, num_pages, page_linked_list, OperationType::MapGroup));
-
- // Succeeded in allocation, commit the resource reservation
- memory_reservation.Commit();
-
- block_manager->Update(current_heap_addr, num_pages, MemoryState::Normal,
- MemoryPermission::ReadAndWrite);
-
- current_heap_addr = heap_region_start + size;
- }
-
- return MakeResult<VAddr>(heap_region_start);
-}
-
-ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
- bool is_map_only, VAddr region_start,
- std::size_t region_num_pages, MemoryState state,
- MemoryPermission perm, PAddr map_addr) {
- std::lock_guard lock{page_table_lock};
-
- if (!CanContain(region_start, region_num_pages * PageSize, state)) {
- return ResultInvalidCurrentMemory;
- }
-
- if (region_num_pages <= needed_num_pages) {
- return ResultOutOfMemory;
- }
-
- const VAddr addr{
- AllocateVirtualMemory(region_start, region_num_pages, needed_num_pages, align)};
- if (!addr) {
- return ResultOutOfMemory;
- }
-
- if (is_map_only) {
- CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr));
- } else {
- PageLinkedList page_group;
- CASCADE_CODE(
- system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, memory_pool));
- CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup));
- }
-
- block_manager->Update(addr, needed_num_pages, state, perm);
-
- return MakeResult<VAddr>(addr);
-}
-
-ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- MemoryPermission perm{};
- if (const ResultCode result{CheckMemoryState(
- nullptr, &perm, nullptr, addr, size, MemoryState::FlagCanChangeAttribute,
- MemoryState::FlagCanChangeAttribute, MemoryPermission::None, MemoryPermission::None,
- MemoryAttribute::LockedAndIpcLocked, MemoryAttribute::None,
- MemoryAttribute::DeviceSharedAndUncached)};
- result.IsError()) {
- return result;
- }
-
- block_manager->UpdateLock(
- addr, size / PageSize,
- [](MemoryBlockManager::iterator block, MemoryPermission perm) {
- block->ShareToDevice(perm);
- },
- perm);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) {
- std::lock_guard lock{page_table_lock};
-
- MemoryPermission perm{};
- if (const ResultCode result{CheckMemoryState(
- nullptr, &perm, nullptr, addr, size, MemoryState::FlagCanChangeAttribute,
- MemoryState::FlagCanChangeAttribute, MemoryPermission::None, MemoryPermission::None,
- MemoryAttribute::LockedAndIpcLocked, MemoryAttribute::None,
- MemoryAttribute::DeviceSharedAndUncached)};
- result.IsError()) {
- return result;
- }
-
- block_manager->UpdateLock(
- addr, size / PageSize,
- [](MemoryBlockManager::iterator block, MemoryPermission perm) {
- block->UnshareToDevice(perm);
- },
- perm);
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::InitializeMemoryLayout(VAddr start, VAddr end) {
- block_manager = std::make_unique<MemoryBlockManager>(start, end);
-
- return RESULT_SUCCESS;
-}
-
-bool PageTable::IsRegionMapped(VAddr address, u64 size) {
- return CheckMemoryState(address, size, MemoryState::All, MemoryState::Free,
- MemoryPermission::Mask, MemoryPermission::None, MemoryAttribute::Mask,
- MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped)
- .IsError();
-}
-
-bool PageTable::IsRegionContiguous(VAddr addr, u64 size) const {
- auto start_ptr = system.Memory().GetPointer(addr);
- for (u64 offset{}; offset < size; offset += PageSize) {
- if (start_ptr != system.Memory().GetPointer(addr + offset)) {
- return false;
- }
- start_ptr += PageSize;
- }
- return true;
-}
-
-void PageTable::AddRegionToPages(VAddr start, std::size_t num_pages,
- PageLinkedList& page_linked_list) {
- VAddr addr{start};
- while (addr < start + (num_pages * PageSize)) {
- const PAddr paddr{GetPhysicalAddr(addr)};
- if (!paddr) {
- UNREACHABLE();
- }
- page_linked_list.AddBlock(paddr, 1);
- addr += PageSize;
- }
-}
-
-VAddr PageTable::AllocateVirtualMemory(VAddr start, std::size_t region_num_pages,
- u64 needed_num_pages, std::size_t align) {
- if (is_aslr_enabled) {
- UNIMPLEMENTED();
- }
- return block_manager->FindFreeArea(start, region_num_pages, needed_num_pages, align, 0,
- IsKernel() ? 1 : 4);
-}
-
-ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group,
- OperationType operation) {
- std::lock_guard lock{page_table_lock};
-
- ASSERT(Common::IsAligned(addr, PageSize));
- ASSERT(num_pages > 0);
- ASSERT(num_pages == page_group.GetNumPages());
-
- for (const auto& node : page_group.Nodes()) {
- const std::size_t size{node.GetNumPages() * PageSize};
-
- switch (operation) {
- case OperationType::MapGroup:
- system.Memory().MapMemoryRegion(page_table_impl, addr, size, node.GetAddress());
- break;
- default:
- UNREACHABLE();
- }
-
- addr += size;
- }
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm,
- OperationType operation, PAddr map_addr) {
- std::lock_guard lock{page_table_lock};
-
- ASSERT(num_pages > 0);
- ASSERT(Common::IsAligned(addr, PageSize));
- ASSERT(ContainsPages(addr, num_pages));
-
- switch (operation) {
- case OperationType::Unmap:
- system.Memory().UnmapRegion(page_table_impl, addr, num_pages * PageSize);
- break;
- case OperationType::Map: {
- ASSERT(map_addr);
- ASSERT(Common::IsAligned(map_addr, PageSize));
- system.Memory().MapMemoryRegion(page_table_impl, addr, num_pages * PageSize, map_addr);
- break;
- }
- case OperationType::ChangePermissions:
- case OperationType::ChangePermissionsAndRefresh:
- break;
- default:
- UNREACHABLE();
- }
- return RESULT_SUCCESS;
-}
-
-constexpr VAddr PageTable::GetRegionAddress(MemoryState state) const {
- switch (state) {
- case MemoryState::Free:
- case MemoryState::Kernel:
- return address_space_start;
- case MemoryState::Normal:
- return heap_region_start;
- case MemoryState::Ipc:
- case MemoryState::NonSecureIpc:
- case MemoryState::NonDeviceIpc:
- return alias_region_start;
- case MemoryState::Stack:
- return stack_region_start;
- case MemoryState::Io:
- case MemoryState::Static:
- case MemoryState::ThreadLocal:
- return kernel_map_region_start;
- case MemoryState::Shared:
- case MemoryState::AliasCode:
- case MemoryState::AliasCodeData:
- case MemoryState::Transferred:
- case MemoryState::SharedTransferred:
- case MemoryState::SharedCode:
- case MemoryState::GeneratedCode:
- case MemoryState::CodeOut:
- return alias_code_region_start;
- case MemoryState::Code:
- case MemoryState::CodeData:
- return code_region_start;
- default:
- UNREACHABLE();
- return {};
- }
-}
-
-constexpr std::size_t PageTable::GetRegionSize(MemoryState state) const {
- switch (state) {
- case MemoryState::Free:
- case MemoryState::Kernel:
- return address_space_end - address_space_start;
- case MemoryState::Normal:
- return heap_region_end - heap_region_start;
- case MemoryState::Ipc:
- case MemoryState::NonSecureIpc:
- case MemoryState::NonDeviceIpc:
- return alias_region_end - alias_region_start;
- case MemoryState::Stack:
- return stack_region_end - stack_region_start;
- case MemoryState::Io:
- case MemoryState::Static:
- case MemoryState::ThreadLocal:
- return kernel_map_region_end - kernel_map_region_start;
- case MemoryState::Shared:
- case MemoryState::AliasCode:
- case MemoryState::AliasCodeData:
- case MemoryState::Transferred:
- case MemoryState::SharedTransferred:
- case MemoryState::SharedCode:
- case MemoryState::GeneratedCode:
- case MemoryState::CodeOut:
- return alias_code_region_end - alias_code_region_start;
- case MemoryState::Code:
- case MemoryState::CodeData:
- return code_region_end - code_region_start;
- default:
- UNREACHABLE();
- return {};
- }
-}
-
-constexpr bool PageTable::CanContain(VAddr addr, std::size_t size, MemoryState state) const {
- const VAddr end{addr + size};
- const VAddr last{end - 1};
- const VAddr region_start{GetRegionAddress(state)};
- const std::size_t region_size{GetRegionSize(state)};
- const bool is_in_region{region_start <= addr && addr < end &&
- last <= region_start + region_size - 1};
- const bool is_in_heap{!(end <= heap_region_start || heap_region_end <= addr)};
- const bool is_in_alias{!(end <= alias_region_start || alias_region_end <= addr)};
-
- switch (state) {
- case MemoryState::Free:
- case MemoryState::Kernel:
- return is_in_region;
- case MemoryState::Io:
- case MemoryState::Static:
- case MemoryState::Code:
- case MemoryState::CodeData:
- case MemoryState::Shared:
- case MemoryState::AliasCode:
- case MemoryState::AliasCodeData:
- case MemoryState::Stack:
- case MemoryState::ThreadLocal:
- case MemoryState::Transferred:
- case MemoryState::SharedTransferred:
- case MemoryState::SharedCode:
- case MemoryState::GeneratedCode:
- case MemoryState::CodeOut:
- return is_in_region && !is_in_heap && !is_in_alias;
- case MemoryState::Normal:
- ASSERT(is_in_heap);
- return is_in_region && !is_in_alias;
- case MemoryState::Ipc:
- case MemoryState::NonSecureIpc:
- case MemoryState::NonDeviceIpc:
- ASSERT(is_in_alias);
- return is_in_region && !is_in_heap;
- default:
- return false;
- }
-}
-
-constexpr ResultCode PageTable::CheckMemoryState(const MemoryInfo& info, MemoryState state_mask,
- MemoryState state, MemoryPermission perm_mask,
- MemoryPermission perm, MemoryAttribute attr_mask,
- MemoryAttribute attr) const {
- // Validate the states match expectation
- if ((info.state & state_mask) != state) {
- return ResultInvalidCurrentMemory;
- }
- if ((info.perm & perm_mask) != perm) {
- return ResultInvalidCurrentMemory;
- }
- if ((info.attribute & attr_mask) != attr) {
- return ResultInvalidCurrentMemory;
- }
-
- return RESULT_SUCCESS;
-}
-
-ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission* out_perm,
- MemoryAttribute* out_attr, VAddr addr, std::size_t size,
- MemoryState state_mask, MemoryState state,
- MemoryPermission perm_mask, MemoryPermission perm,
- MemoryAttribute attr_mask, MemoryAttribute attr,
- MemoryAttribute ignore_attr) {
- std::lock_guard lock{page_table_lock};
-
- // Get information about the first block
- const VAddr last_addr{addr + size - 1};
- MemoryBlockManager::const_iterator it{block_manager->FindIterator(addr)};
- MemoryInfo info{it->GetMemoryInfo()};
-
- // Validate all blocks in the range have correct state
- const MemoryState first_state{info.state};
- const MemoryPermission first_perm{info.perm};
- const MemoryAttribute first_attr{info.attribute};
-
- while (true) {
- // Validate the current block
- if (!(info.state == first_state)) {
- return ResultInvalidCurrentMemory;
- }
- if (!(info.perm == first_perm)) {
- return ResultInvalidCurrentMemory;
- }
- if (!((info.attribute | static_cast<MemoryAttribute>(ignore_attr)) ==
- (first_attr | static_cast<MemoryAttribute>(ignore_attr)))) {
- return ResultInvalidCurrentMemory;
- }
-
- // Validate against the provided masks
- CASCADE_CODE(CheckMemoryState(info, state_mask, state, perm_mask, perm, attr_mask, attr));
-
- // Break once we're done
- if (last_addr <= info.GetLastAddress()) {
- break;
- }
-
- // Advance our iterator
- it++;
- ASSERT(it != block_manager->cend());
- info = it->GetMemoryInfo();
- }
-
- // Write output state
- if (out_state) {
- *out_state = first_state;
- }
- if (out_perm) {
- *out_perm = first_perm;
- }
- if (out_attr) {
- *out_attr = first_attr & static_cast<MemoryAttribute>(~ignore_attr);
- }
-
- return RESULT_SUCCESS;
-}
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/page_table.h b/src/core/hle/kernel/memory/page_table.h
deleted file mode 100644
index ce0d38849..000000000
--- a/src/core/hle/kernel/memory/page_table.h
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include <mutex>
-
-#include "common/common_types.h"
-#include "common/page_table.h"
-#include "core/file_sys/program_metadata.h"
-#include "core/hle/kernel/memory/memory_block.h"
-#include "core/hle/kernel/memory/memory_manager.h"
-#include "core/hle/result.h"
-
-namespace Core {
-class System;
-}
-
-namespace Kernel::Memory {
-
-class MemoryBlockManager;
-
-class PageTable final : NonCopyable {
-public:
- explicit PageTable(Core::System& system);
-
- ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr,
- VAddr code_addr, std::size_t code_size,
- Memory::MemoryManager::Pool pool);
- ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, MemoryState state,
- MemoryPermission perm);
- ResultCode MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
- ResultCode UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
- ResultCode MapPhysicalMemory(VAddr addr, std::size_t size);
- ResultCode UnmapPhysicalMemory(VAddr addr, std::size_t size);
- ResultCode UnmapMemory(VAddr addr, std::size_t size);
- ResultCode Map(VAddr dst_addr, VAddr src_addr, std::size_t size);
- ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size);
- ResultCode MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state,
- MemoryPermission perm);
- ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm);
- MemoryInfo QueryInfo(VAddr addr);
- ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm);
- ResultCode ResetTransferMemory(VAddr addr, std::size_t size);
- ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask,
- MemoryAttribute value);
- ResultCode SetHeapCapacity(std::size_t new_heap_capacity);
- ResultVal<VAddr> SetHeapSize(std::size_t size);
- ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
- bool is_map_only, VAddr region_start,
- std::size_t region_num_pages, MemoryState state,
- MemoryPermission perm, PAddr map_addr = 0);
- ResultCode LockForDeviceAddressSpace(VAddr addr, std::size_t size);
- ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size);
-
- Common::PageTable& PageTableImpl() {
- return page_table_impl;
- }
-
- const Common::PageTable& PageTableImpl() const {
- return page_table_impl;
- }
-
-private:
- enum class OperationType : u32 {
- Map,
- MapGroup,
- Unmap,
- ChangePermissions,
- ChangePermissionsAndRefresh,
- };
-
- static constexpr MemoryAttribute DefaultMemoryIgnoreAttr =
- MemoryAttribute::DontCareMask | MemoryAttribute::IpcLocked | MemoryAttribute::DeviceShared;
-
- ResultCode InitializeMemoryLayout(VAddr start, VAddr end);
- ResultCode MapPages(VAddr addr, const PageLinkedList& page_linked_list, MemoryPermission perm);
- void MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, VAddr end);
- bool IsRegionMapped(VAddr address, u64 size);
- bool IsRegionContiguous(VAddr addr, u64 size) const;
- void AddRegionToPages(VAddr start, std::size_t num_pages, PageLinkedList& page_linked_list);
- MemoryInfo QueryInfoImpl(VAddr addr);
- VAddr AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, u64 needed_num_pages,
- std::size_t align);
- ResultCode Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group,
- OperationType operation);
- ResultCode Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm,
- OperationType operation, PAddr map_addr = 0);
- constexpr VAddr GetRegionAddress(MemoryState state) const;
- constexpr std::size_t GetRegionSize(MemoryState state) const;
- constexpr bool CanContain(VAddr addr, std::size_t size, MemoryState state) const;
-
- constexpr ResultCode CheckMemoryState(const MemoryInfo& info, MemoryState state_mask,
- MemoryState state, MemoryPermission perm_mask,
- MemoryPermission perm, MemoryAttribute attr_mask,
- MemoryAttribute attr) const;
- ResultCode CheckMemoryState(MemoryState* out_state, MemoryPermission* out_perm,
- MemoryAttribute* out_attr, VAddr addr, std::size_t size,
- MemoryState state_mask, MemoryState state,
- MemoryPermission perm_mask, MemoryPermission perm,
- MemoryAttribute attr_mask, MemoryAttribute attr,
- MemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr);
- ResultCode CheckMemoryState(VAddr addr, std::size_t size, MemoryState state_mask,
- MemoryState state, MemoryPermission perm_mask,
- MemoryPermission perm, MemoryAttribute attr_mask,
- MemoryAttribute attr,
- MemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) {
- return CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask,
- perm, attr_mask, attr, ignore_attr);
- }
-
- std::recursive_mutex page_table_lock;
- std::unique_ptr<MemoryBlockManager> block_manager;
-
-public:
- constexpr VAddr GetAddressSpaceStart() const {
- return address_space_start;
- }
- constexpr VAddr GetAddressSpaceEnd() const {
- return address_space_end;
- }
- constexpr std::size_t GetAddressSpaceSize() const {
- return address_space_end - address_space_start;
- }
- constexpr VAddr GetHeapRegionStart() const {
- return heap_region_start;
- }
- constexpr VAddr GetHeapRegionEnd() const {
- return heap_region_end;
- }
- constexpr std::size_t GetHeapRegionSize() const {
- return heap_region_end - heap_region_start;
- }
- constexpr VAddr GetAliasRegionStart() const {
- return alias_region_start;
- }
- constexpr VAddr GetAliasRegionEnd() const {
- return alias_region_end;
- }
- constexpr std::size_t GetAliasRegionSize() const {
- return alias_region_end - alias_region_start;
- }
- constexpr VAddr GetStackRegionStart() const {
- return stack_region_start;
- }
- constexpr VAddr GetStackRegionEnd() const {
- return stack_region_end;
- }
- constexpr std::size_t GetStackRegionSize() const {
- return stack_region_end - stack_region_start;
- }
- constexpr VAddr GetKernelMapRegionStart() const {
- return kernel_map_region_start;
- }
- constexpr VAddr GetKernelMapRegionEnd() const {
- return kernel_map_region_end;
- }
- constexpr VAddr GetCodeRegionStart() const {
- return code_region_start;
- }
- constexpr VAddr GetCodeRegionEnd() const {
- return code_region_end;
- }
- constexpr VAddr GetAliasCodeRegionStart() const {
- return alias_code_region_start;
- }
- constexpr VAddr GetAliasCodeRegionSize() const {
- return alias_code_region_end - alias_code_region_start;
- }
- constexpr std::size_t GetAddressSpaceWidth() const {
- return address_space_width;
- }
- constexpr std::size_t GetHeapSize() {
- return current_heap_addr - heap_region_start;
- }
- constexpr std::size_t GetTotalHeapSize() {
- return GetHeapSize() + physical_memory_usage;
- }
- constexpr bool IsInsideAddressSpace(VAddr address, std::size_t size) const {
- return address_space_start <= address && address + size - 1 <= address_space_end - 1;
- }
- constexpr bool IsOutsideAliasRegion(VAddr address, std::size_t size) const {
- return alias_region_start > address || address + size - 1 > alias_region_end - 1;
- }
- constexpr bool IsOutsideStackRegion(VAddr address, std::size_t size) const {
- return stack_region_start > address || address + size - 1 > stack_region_end - 1;
- }
- constexpr bool IsInvalidRegion(VAddr address, std::size_t size) const {
- return address + size - 1 > GetAliasCodeRegionStart() + GetAliasCodeRegionSize() - 1;
- }
- constexpr bool IsInsideHeapRegion(VAddr address, std::size_t size) const {
- return address + size > heap_region_start && heap_region_end > address;
- }
- constexpr bool IsInsideAliasRegion(VAddr address, std::size_t size) const {
- return address + size > alias_region_start && alias_region_end > address;
- }
- constexpr bool IsOutsideASLRRegion(VAddr address, std::size_t size) const {
- if (IsInvalidRegion(address, size)) {
- return true;
- }
- if (IsInsideHeapRegion(address, size)) {
- return true;
- }
- if (IsInsideAliasRegion(address, size)) {
- return true;
- }
- return {};
- }
- constexpr bool IsInsideASLRRegion(VAddr address, std::size_t size) const {
- return !IsOutsideASLRRegion(address, size);
- }
- constexpr PAddr GetPhysicalAddr(VAddr addr) {
- return page_table_impl.backing_addr[addr >> Memory::PageBits] + addr;
- }
-
-private:
- constexpr bool Contains(VAddr addr) const {
- return address_space_start <= addr && addr <= address_space_end - 1;
- }
- constexpr bool Contains(VAddr addr, std::size_t size) const {
- return address_space_start <= addr && addr < addr + size &&
- addr + size - 1 <= address_space_end - 1;
- }
- constexpr bool IsKernel() const {
- return is_kernel;
- }
- constexpr bool IsAslrEnabled() const {
- return is_aslr_enabled;
- }
-
- constexpr std::size_t GetNumGuardPages() const {
- return IsKernel() ? 1 : 4;
- }
-
- constexpr bool ContainsPages(VAddr addr, std::size_t num_pages) const {
- return (address_space_start <= addr) &&
- (num_pages <= (address_space_end - address_space_start) / PageSize) &&
- (addr + num_pages * PageSize - 1 <= address_space_end - 1);
- }
-
-private:
- VAddr address_space_start{};
- VAddr address_space_end{};
- VAddr heap_region_start{};
- VAddr heap_region_end{};
- VAddr current_heap_end{};
- VAddr alias_region_start{};
- VAddr alias_region_end{};
- VAddr stack_region_start{};
- VAddr stack_region_end{};
- VAddr kernel_map_region_start{};
- VAddr kernel_map_region_end{};
- VAddr code_region_start{};
- VAddr code_region_end{};
- VAddr alias_code_region_start{};
- VAddr alias_code_region_end{};
- VAddr current_heap_addr{};
-
- std::size_t heap_capacity{};
- std::size_t physical_memory_usage{};
- std::size_t max_heap_size{};
- std::size_t max_physical_memory_size{};
- std::size_t address_space_width{};
-
- bool is_kernel{};
- bool is_aslr_enabled{};
-
- MemoryManager::Pool memory_pool{MemoryManager::Pool::Application};
-
- Common::PageTable page_table_impl;
-
- Core::System& system;
-};
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/slab_heap.h b/src/core/hle/kernel/memory/slab_heap.h
deleted file mode 100644
index 465eaddb3..000000000
--- a/src/core/hle/kernel/memory/slab_heap.h
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
-#pragma once
-
-#include <atomic>
-
-#include "common/assert.h"
-#include "common/common_types.h"
-
-namespace Kernel::Memory {
-
-namespace impl {
-
-class SlabHeapImpl final : NonCopyable {
-public:
- struct Node {
- Node* next{};
- };
-
- constexpr SlabHeapImpl() = default;
-
- void Initialize(std::size_t size) {
- ASSERT(head == nullptr);
- obj_size = size;
- }
-
- constexpr std::size_t GetObjectSize() const {
- return obj_size;
- }
-
- Node* GetHead() const {
- return head;
- }
-
- void* Allocate() {
- Node* ret = head.load();
-
- do {
- if (ret == nullptr) {
- break;
- }
- } while (!head.compare_exchange_weak(ret, ret->next));
-
- return ret;
- }
-
- void Free(void* obj) {
- Node* node = static_cast<Node*>(obj);
-
- Node* cur_head = head.load();
- do {
- node->next = cur_head;
- } while (!head.compare_exchange_weak(cur_head, node));
- }
-
-private:
- std::atomic<Node*> head{};
- std::size_t obj_size{};
-};
-
-} // namespace impl
-
-class SlabHeapBase : NonCopyable {
-public:
- constexpr SlabHeapBase() = default;
-
- constexpr bool Contains(uintptr_t addr) const {
- return start <= addr && addr < end;
- }
-
- constexpr std::size_t GetSlabHeapSize() const {
- return (end - start) / GetObjectSize();
- }
-
- constexpr std::size_t GetObjectSize() const {
- return impl.GetObjectSize();
- }
-
- constexpr uintptr_t GetSlabHeapAddress() const {
- return start;
- }
-
- std::size_t GetObjectIndexImpl(const void* obj) const {
- return (reinterpret_cast<uintptr_t>(obj) - start) / GetObjectSize();
- }
-
- std::size_t GetPeakIndex() const {
- return GetObjectIndexImpl(reinterpret_cast<const void*>(peak));
- }
-
- void* AllocateImpl() {
- return impl.Allocate();
- }
-
- void FreeImpl(void* obj) {
- // Don't allow freeing an object that wasn't allocated from this heap
- ASSERT(Contains(reinterpret_cast<uintptr_t>(obj)));
- impl.Free(obj);
- }
-
- void InitializeImpl(std::size_t obj_size, void* memory, std::size_t memory_size) {
- // Ensure we don't initialize a slab using null memory
- ASSERT(memory != nullptr);
-
- // Initialize the base allocator
- impl.Initialize(obj_size);
-
- // Set our tracking variables
- const std::size_t num_obj = (memory_size / obj_size);
- start = reinterpret_cast<uintptr_t>(memory);
- end = start + num_obj * obj_size;
- peak = start;
-
- // Free the objects
- u8* cur = reinterpret_cast<u8*>(end);
-
- for (std::size_t i{}; i < num_obj; i++) {
- cur -= obj_size;
- impl.Free(cur);
- }
- }
-
-private:
- using Impl = impl::SlabHeapImpl;
-
- Impl impl;
- uintptr_t peak{};
- uintptr_t start{};
- uintptr_t end{};
-};
-
-template <typename T>
-class SlabHeap final : public SlabHeapBase {
-public:
- constexpr SlabHeap() : SlabHeapBase() {}
-
- void Initialize(void* memory, std::size_t memory_size) {
- InitializeImpl(sizeof(T), memory, memory_size);
- }
-
- T* Allocate() {
- T* obj = static_cast<T*>(AllocateImpl());
- if (obj != nullptr) {
- new (obj) T();
- }
- return obj;
- }
-
- void Free(T* obj) {
- FreeImpl(obj);
- }
-
- constexpr std::size_t GetObjectIndex(const T* obj) const {
- return GetObjectIndexImpl(obj);
- }
-};
-
-} // namespace Kernel::Memory
diff --git a/src/core/hle/kernel/memory/system_control.cpp b/src/core/hle/kernel/memory/system_control.cpp
deleted file mode 100644
index 11d204bc2..000000000
--- a/src/core/hle/kernel/memory/system_control.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <random>
-
-#include "core/hle/kernel/memory/system_control.h"
-
-namespace Kernel::Memory::SystemControl {
-namespace {
-template <typename F>
-u64 GenerateUniformRange(u64 min, u64 max, F f) {
- // Handle the case where the difference is too large to represent.
- if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) {
- return f();
- }
-
- // Iterate until we get a value in range.
- const u64 range_size = ((max + 1) - min);
- const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
- while (true) {
- if (const u64 rnd = f(); rnd < effective_max) {
- return min + (rnd % range_size);
- }
- }
-}
-
-u64 GenerateRandomU64ForInit() {
- static std::random_device device;
- static std::mt19937 gen(device());
- static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
- return distribution(gen);
-}
-} // Anonymous namespace
-
-u64 GenerateRandomRange(u64 min, u64 max) {
- return GenerateUniformRange(min, max, GenerateRandomU64ForInit);
-}
-
-} // namespace Kernel::Memory::SystemControl
diff --git a/src/core/hle/kernel/memory/system_control.h b/src/core/hle/kernel/memory/system_control.h
deleted file mode 100644
index 19cab8cbc..000000000
--- a/src/core/hle/kernel/memory/system_control.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "common/common_types.h"
-
-namespace Kernel::Memory::SystemControl {
-
-u64 GenerateRandomRange(u64 min, u64 max);
-
-} // namespace Kernel::Memory::SystemControl