diff options
| author | 2021-02-27 12:48:35 -0700 | |
|---|---|---|
| committer | 2021-02-27 12:48:35 -0700 | |
| commit | 09f7c355c6d7e3c7845ba96d9704489d2d5853f4 (patch) | |
| tree | b12127263c0e4999f0a6e9edfe7f8f25adef9d37 | |
| parent | Merge pull request #5944 from Morph1984/gc-vibrations (diff) | |
| parent | hle: kernel: Migrate PageHeap/PageTable to KPageHeap/KPageTable. (diff) | |
| download | yuzu-09f7c355c6d7e3c7845ba96d9704489d2d5853f4.tar.gz yuzu-09f7c355c6d7e3c7845ba96d9704489d2d5853f4.tar.xz yuzu-09f7c355c6d7e3c7845ba96d9704489d2d5853f4.zip | |
Merge pull request #5953 from bunnei/memory-refactor-1
Kernel Rework: Memory updates and refactoring (Part 1)
56 files changed, 1690 insertions, 1212 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index b657506b1..788516ded 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -167,6 +167,7 @@ add_library(common STATIC | |||
| 167 | threadsafe_queue.h | 167 | threadsafe_queue.h |
| 168 | time_zone.cpp | 168 | time_zone.cpp |
| 169 | time_zone.h | 169 | time_zone.h |
| 170 | tiny_mt.h | ||
| 170 | tree.h | 171 | tree.h |
| 171 | uint128.h | 172 | uint128.h |
| 172 | uuid.cpp | 173 | uuid.cpp |
diff --git a/src/common/alignment.h b/src/common/alignment.h index fb81f10d8..32d796ffa 100644 --- a/src/common/alignment.h +++ b/src/common/alignment.h | |||
| @@ -42,6 +42,11 @@ requires std::is_integral_v<T>[[nodiscard]] constexpr bool IsAligned(T value, si | |||
| 42 | return (value & mask) == 0; | 42 | return (value & mask) == 0; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | template <typename T, typename U> | ||
| 46 | requires std::is_integral_v<T>[[nodiscard]] constexpr T DivideUp(T x, U y) { | ||
| 47 | return (x + (y - 1)) / y; | ||
| 48 | } | ||
| 49 | |||
| 45 | template <typename T, size_t Align = 16> | 50 | template <typename T, size_t Align = 16> |
| 46 | class AlignmentAllocator { | 51 | class AlignmentAllocator { |
| 47 | public: | 52 | public: |
diff --git a/src/common/tiny_mt.h b/src/common/tiny_mt.h new file mode 100644 index 000000000..19ae5b7d6 --- /dev/null +++ b/src/common/tiny_mt.h | |||
| @@ -0,0 +1,250 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | |||
| 9 | #include "common/alignment.h" | ||
| 10 | #include "common/common_types.h" | ||
| 11 | |||
| 12 | namespace Common { | ||
| 13 | |||
| 14 | // Implementation of TinyMT (mersenne twister RNG). | ||
| 15 | // Like Nintendo, we will use the sample parameters. | ||
| 16 | class TinyMT { | ||
| 17 | public: | ||
| 18 | static constexpr std::size_t NumStateWords = 4; | ||
| 19 | |||
| 20 | struct State { | ||
| 21 | std::array<u32, NumStateWords> data{}; | ||
| 22 | }; | ||
| 23 | |||
| 24 | private: | ||
| 25 | static constexpr u32 ParamMat1 = 0x8F7011EE; | ||
| 26 | static constexpr u32 ParamMat2 = 0xFC78FF1F; | ||
| 27 | static constexpr u32 ParamTmat = 0x3793FDFF; | ||
| 28 | |||
| 29 | static constexpr u32 ParamMult = 0x6C078965; | ||
| 30 | static constexpr u32 ParamPlus = 0x0019660D; | ||
| 31 | static constexpr u32 ParamXor = 0x5D588B65; | ||
| 32 | |||
| 33 | static constexpr u32 TopBitmask = 0x7FFFFFFF; | ||
| 34 | |||
| 35 | static constexpr int MinimumInitIterations = 8; | ||
| 36 | static constexpr int NumDiscardedInitOutputs = 8; | ||
| 37 | |||
| 38 | static constexpr u32 XorByShifted27(u32 value) { | ||
| 39 | return value ^ (value >> 27); | ||
| 40 | } | ||
| 41 | |||
| 42 | static constexpr u32 XorByShifted30(u32 value) { | ||
| 43 | return value ^ (value >> 30); | ||
| 44 | } | ||
| 45 | |||
| 46 | private: | ||
| 47 | State state{}; | ||
| 48 | |||
| 49 | private: | ||
| 50 | // Internal API. | ||
| 51 | void FinalizeInitialization() { | ||
| 52 | const u32 state0 = this->state.data[0] & TopBitmask; | ||
| 53 | const u32 state1 = this->state.data[1]; | ||
| 54 | const u32 state2 = this->state.data[2]; | ||
| 55 | const u32 state3 = this->state.data[3]; | ||
| 56 | |||
| 57 | if (state0 == 0 && state1 == 0 && state2 == 0 && state3 == 0) { | ||
| 58 | this->state.data[0] = 'T'; | ||
| 59 | this->state.data[1] = 'I'; | ||
| 60 | this->state.data[2] = 'N'; | ||
| 61 | this->state.data[3] = 'Y'; | ||
| 62 | } | ||
| 63 | |||
| 64 | for (int i = 0; i < NumDiscardedInitOutputs; i++) { | ||
| 65 | this->GenerateRandomU32(); | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | u32 GenerateRandomU24() { | ||
| 70 | return (this->GenerateRandomU32() >> 8); | ||
| 71 | } | ||
| 72 | |||
| 73 | static void GenerateInitialValuePlus(TinyMT::State* state, int index, u32 value) { | ||
| 74 | u32& state0 = state->data[(index + 0) % NumStateWords]; | ||
| 75 | u32& state1 = state->data[(index + 1) % NumStateWords]; | ||
| 76 | u32& state2 = state->data[(index + 2) % NumStateWords]; | ||
| 77 | u32& state3 = state->data[(index + 3) % NumStateWords]; | ||
| 78 | |||
| 79 | const u32 x = XorByShifted27(state0 ^ state1 ^ state3) * ParamPlus; | ||
| 80 | const u32 y = x + index + value; | ||
| 81 | |||
| 82 | state0 = y; | ||
| 83 | state1 += x; | ||
| 84 | state2 += y; | ||
| 85 | } | ||
| 86 | |||
| 87 | static void GenerateInitialValueXor(TinyMT::State* state, int index) { | ||
| 88 | u32& state0 = state->data[(index + 0) % NumStateWords]; | ||
| 89 | u32& state1 = state->data[(index + 1) % NumStateWords]; | ||
| 90 | u32& state2 = state->data[(index + 2) % NumStateWords]; | ||
| 91 | u32& state3 = state->data[(index + 3) % NumStateWords]; | ||
| 92 | |||
| 93 | const u32 x = XorByShifted27(state0 + state1 + state3) * ParamXor; | ||
| 94 | const u32 y = x - index; | ||
| 95 | |||
| 96 | state0 = y; | ||
| 97 | state1 ^= x; | ||
| 98 | state2 ^= y; | ||
| 99 | } | ||
| 100 | |||
| 101 | public: | ||
| 102 | constexpr TinyMT() = default; | ||
| 103 | |||
| 104 | // Public API. | ||
| 105 | |||
| 106 | // Initialization. | ||
| 107 | void Initialize(u32 seed) { | ||
| 108 | this->state.data[0] = seed; | ||
| 109 | this->state.data[1] = ParamMat1; | ||
| 110 | this->state.data[2] = ParamMat2; | ||
| 111 | this->state.data[3] = ParamTmat; | ||
| 112 | |||
| 113 | for (int i = 1; i < MinimumInitIterations; i++) { | ||
| 114 | const u32 mixed = XorByShifted30(this->state.data[(i - 1) % NumStateWords]); | ||
| 115 | this->state.data[i % NumStateWords] ^= mixed * ParamMult + i; | ||
| 116 | } | ||
| 117 | |||
| 118 | this->FinalizeInitialization(); | ||
| 119 | } | ||
| 120 | |||
| 121 | void Initialize(const u32* seed, int seed_count) { | ||
| 122 | this->state.data[0] = 0; | ||
| 123 | this->state.data[1] = ParamMat1; | ||
| 124 | this->state.data[2] = ParamMat2; | ||
| 125 | this->state.data[3] = ParamTmat; | ||
| 126 | |||
| 127 | { | ||
| 128 | const int num_init_iterations = std::max(seed_count + 1, MinimumInitIterations) - 1; | ||
| 129 | |||
| 130 | GenerateInitialValuePlus(&this->state, 0, seed_count); | ||
| 131 | |||
| 132 | for (int i = 0; i < num_init_iterations; i++) { | ||
| 133 | GenerateInitialValuePlus(&this->state, (i + 1) % NumStateWords, | ||
| 134 | (i < seed_count) ? seed[i] : 0); | ||
| 135 | } | ||
| 136 | |||
| 137 | for (int i = 0; i < static_cast<int>(NumStateWords); i++) { | ||
| 138 | GenerateInitialValueXor(&this->state, | ||
| 139 | (i + 1 + num_init_iterations) % NumStateWords); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | this->FinalizeInitialization(); | ||
| 144 | } | ||
| 145 | |||
| 146 | // State management. | ||
| 147 | void GetState(TinyMT::State& out) const { | ||
| 148 | out.data = this->state.data; | ||
| 149 | } | ||
| 150 | |||
| 151 | void SetState(const TinyMT::State& state_) { | ||
| 152 | this->state.data = state_.data; | ||
| 153 | } | ||
| 154 | |||
| 155 | // Random generation. | ||
| 156 | void GenerateRandomBytes(void* dst, std::size_t size) { | ||
| 157 | const uintptr_t start = reinterpret_cast<uintptr_t>(dst); | ||
| 158 | const uintptr_t end = start + size; | ||
| 159 | const uintptr_t aligned_start = Common::AlignUp(start, 4); | ||
| 160 | const uintptr_t aligned_end = Common::AlignDown(end, 4); | ||
| 161 | |||
| 162 | // Make sure we're aligned. | ||
| 163 | if (start < aligned_start) { | ||
| 164 | const u32 rnd = this->GenerateRandomU32(); | ||
| 165 | std::memcpy(dst, &rnd, aligned_start - start); | ||
| 166 | } | ||
| 167 | |||
| 168 | // Write as many aligned u32s as we can. | ||
| 169 | { | ||
| 170 | u32* cur_dst = reinterpret_cast<u32*>(aligned_start); | ||
| 171 | u32* const end_dst = reinterpret_cast<u32*>(aligned_end); | ||
| 172 | |||
| 173 | while (cur_dst < end_dst) { | ||
| 174 | *(cur_dst++) = this->GenerateRandomU32(); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | // Handle any leftover unaligned data. | ||
| 179 | if (aligned_end < end) { | ||
| 180 | const u32 rnd = this->GenerateRandomU32(); | ||
| 181 | std::memcpy(reinterpret_cast<void*>(aligned_end), &rnd, end - aligned_end); | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | u32 GenerateRandomU32() { | ||
| 186 | // Advance state. | ||
| 187 | const u32 x0 = | ||
| 188 | (this->state.data[0] & TopBitmask) ^ this->state.data[1] ^ this->state.data[2]; | ||
| 189 | const u32 y0 = this->state.data[3]; | ||
| 190 | const u32 x1 = x0 ^ (x0 << 1); | ||
| 191 | const u32 y1 = y0 ^ (y0 >> 1) ^ x1; | ||
| 192 | |||
| 193 | const u32 state0 = this->state.data[1]; | ||
| 194 | u32 state1 = this->state.data[2]; | ||
| 195 | u32 state2 = x1 ^ (y1 << 10); | ||
| 196 | const u32 state3 = y1; | ||
| 197 | |||
| 198 | if ((y1 & 1) != 0) { | ||
| 199 | state1 ^= ParamMat1; | ||
| 200 | state2 ^= ParamMat2; | ||
| 201 | } | ||
| 202 | |||
| 203 | this->state.data[0] = state0; | ||
| 204 | this->state.data[1] = state1; | ||
| 205 | this->state.data[2] = state2; | ||
| 206 | this->state.data[3] = state3; | ||
| 207 | |||
| 208 | // Temper. | ||
| 209 | const u32 t1 = state0 + (state2 >> 8); | ||
| 210 | u32 t0 = state3 ^ t1; | ||
| 211 | |||
| 212 | if ((t1 & 1) != 0) { | ||
| 213 | t0 ^= ParamTmat; | ||
| 214 | } | ||
| 215 | |||
| 216 | return t0; | ||
| 217 | } | ||
| 218 | |||
| 219 | u64 GenerateRandomU64() { | ||
| 220 | const u32 lo = this->GenerateRandomU32(); | ||
| 221 | const u32 hi = this->GenerateRandomU32(); | ||
| 222 | return (u64{hi} << 32) | u64{lo}; | ||
| 223 | } | ||
| 224 | |||
| 225 | float GenerateRandomF32() { | ||
| 226 | // Floats have 24 bits of mantissa. | ||
| 227 | constexpr u32 MantissaBits = 24; | ||
| 228 | return static_cast<float>(GenerateRandomU24()) * (1.0f / (1U << MantissaBits)); | ||
| 229 | } | ||
| 230 | |||
| 231 | double GenerateRandomF64() { | ||
| 232 | // Doubles have 53 bits of mantissa. | ||
| 233 | // The smart way to generate 53 bits of random would be to use 32 bits | ||
| 234 | // from the first rnd32() call, and then 21 from the second. | ||
| 235 | // Nintendo does not. They use (32 - 5) = 27 bits from the first rnd32() | ||
| 236 | // call, and (32 - 6) bits from the second. We'll do what they do, but | ||
| 237 | // There's not a clear reason why. | ||
| 238 | constexpr u32 MantissaBits = 53; | ||
| 239 | constexpr u32 Shift1st = (64 - MantissaBits) / 2; | ||
| 240 | constexpr u32 Shift2nd = (64 - MantissaBits) - Shift1st; | ||
| 241 | |||
| 242 | const u32 first = (this->GenerateRandomU32() >> Shift1st); | ||
| 243 | const u32 second = (this->GenerateRandomU32() >> Shift2nd); | ||
| 244 | |||
| 245 | return (1.0 * first * (u64{1} << (32 - Shift2nd)) + second) * | ||
| 246 | (1.0 / (u64{1} << MantissaBits)); | ||
| 247 | } | ||
| 248 | }; | ||
| 249 | |||
| 250 | } // namespace Common | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c6bdf72ec..17f251c37 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -156,6 +156,8 @@ add_library(core STATIC | |||
| 156 | hle/kernel/hle_ipc.h | 156 | hle/kernel/hle_ipc.h |
| 157 | hle/kernel/k_address_arbiter.cpp | 157 | hle/kernel/k_address_arbiter.cpp |
| 158 | hle/kernel/k_address_arbiter.h | 158 | hle/kernel/k_address_arbiter.h |
| 159 | hle/kernel/k_address_space_info.cpp | ||
| 160 | hle/kernel/k_address_space_info.h | ||
| 159 | hle/kernel/k_affinity_mask.h | 161 | hle/kernel/k_affinity_mask.h |
| 160 | hle/kernel/k_condition_variable.cpp | 162 | hle/kernel/k_condition_variable.cpp |
| 161 | hle/kernel/k_condition_variable.h | 163 | hle/kernel/k_condition_variable.h |
| @@ -164,6 +166,18 @@ add_library(core STATIC | |||
| 164 | hle/kernel/k_light_condition_variable.h | 166 | hle/kernel/k_light_condition_variable.h |
| 165 | hle/kernel/k_light_lock.cpp | 167 | hle/kernel/k_light_lock.cpp |
| 166 | hle/kernel/k_light_lock.h | 168 | hle/kernel/k_light_lock.h |
| 169 | hle/kernel/k_memory_block.h | ||
| 170 | hle/kernel/k_memory_block_manager.cpp | ||
| 171 | hle/kernel/k_memory_block_manager.h | ||
| 172 | hle/kernel/k_memory_layout.h | ||
| 173 | hle/kernel/k_memory_manager.cpp | ||
| 174 | hle/kernel/k_memory_manager.h | ||
| 175 | hle/kernel/k_page_bitmap.h | ||
| 176 | hle/kernel/k_page_heap.cpp | ||
| 177 | hle/kernel/k_page_heap.h | ||
| 178 | hle/kernel/k_page_linked_list.h | ||
| 179 | hle/kernel/k_page_table.cpp | ||
| 180 | hle/kernel/k_page_table.h | ||
| 167 | hle/kernel/k_priority_queue.h | 181 | hle/kernel/k_priority_queue.h |
| 168 | hle/kernel/k_readable_event.cpp | 182 | hle/kernel/k_readable_event.cpp |
| 169 | hle/kernel/k_readable_event.h | 183 | hle/kernel/k_readable_event.h |
| @@ -175,8 +189,15 @@ add_library(core STATIC | |||
| 175 | hle/kernel/k_scoped_lock.h | 189 | hle/kernel/k_scoped_lock.h |
| 176 | hle/kernel/k_scoped_resource_reservation.h | 190 | hle/kernel/k_scoped_resource_reservation.h |
| 177 | hle/kernel/k_scoped_scheduler_lock_and_sleep.h | 191 | hle/kernel/k_scoped_scheduler_lock_and_sleep.h |
| 192 | hle/kernel/k_shared_memory.cpp | ||
| 193 | hle/kernel/k_shared_memory.h | ||
| 194 | hle/kernel/k_slab_heap.h | ||
| 195 | hle/kernel/k_spin_lock.cpp | ||
| 196 | hle/kernel/k_spin_lock.h | ||
| 178 | hle/kernel/k_synchronization_object.cpp | 197 | hle/kernel/k_synchronization_object.cpp |
| 179 | hle/kernel/k_synchronization_object.h | 198 | hle/kernel/k_synchronization_object.h |
| 199 | hle/kernel/k_system_control.cpp | ||
| 200 | hle/kernel/k_system_control.h | ||
| 180 | hle/kernel/k_thread.cpp | 201 | hle/kernel/k_thread.cpp |
| 181 | hle/kernel/k_thread.h | 202 | hle/kernel/k_thread.h |
| 182 | hle/kernel/k_thread_queue.h | 203 | hle/kernel/k_thread_queue.h |
| @@ -184,23 +205,7 @@ add_library(core STATIC | |||
| 184 | hle/kernel/k_writable_event.h | 205 | hle/kernel/k_writable_event.h |
| 185 | hle/kernel/kernel.cpp | 206 | hle/kernel/kernel.cpp |
| 186 | hle/kernel/kernel.h | 207 | hle/kernel/kernel.h |
| 187 | hle/kernel/memory/address_space_info.cpp | 208 | hle/kernel/memory_types.h |
| 188 | hle/kernel/memory/address_space_info.h | ||
| 189 | hle/kernel/memory/memory_block.h | ||
| 190 | hle/kernel/memory/memory_block_manager.cpp | ||
| 191 | hle/kernel/memory/memory_block_manager.h | ||
| 192 | hle/kernel/memory/memory_layout.h | ||
| 193 | hle/kernel/memory/memory_manager.cpp | ||
| 194 | hle/kernel/memory/memory_manager.h | ||
| 195 | hle/kernel/memory/memory_types.h | ||
| 196 | hle/kernel/memory/page_linked_list.h | ||
| 197 | hle/kernel/memory/page_heap.cpp | ||
| 198 | hle/kernel/memory/page_heap.h | ||
| 199 | hle/kernel/memory/page_table.cpp | ||
| 200 | hle/kernel/memory/page_table.h | ||
| 201 | hle/kernel/memory/slab_heap.h | ||
| 202 | hle/kernel/memory/system_control.cpp | ||
| 203 | hle/kernel/memory/system_control.h | ||
| 204 | hle/kernel/object.cpp | 209 | hle/kernel/object.cpp |
| 205 | hle/kernel/object.h | 210 | hle/kernel/object.h |
| 206 | hle/kernel/physical_core.cpp | 211 | hle/kernel/physical_core.cpp |
| @@ -218,8 +223,6 @@ add_library(core STATIC | |||
| 218 | hle/kernel/service_thread.h | 223 | hle/kernel/service_thread.h |
| 219 | hle/kernel/session.cpp | 224 | hle/kernel/session.cpp |
| 220 | hle/kernel/session.h | 225 | hle/kernel/session.h |
| 221 | hle/kernel/shared_memory.cpp | ||
| 222 | hle/kernel/shared_memory.h | ||
| 223 | hle/kernel/svc.cpp | 226 | hle/kernel/svc.cpp |
| 224 | hle/kernel/svc.h | 227 | hle/kernel/svc.h |
| 225 | hle/kernel/svc_common.h | 228 | hle/kernel/svc_common.h |
diff --git a/src/core/hle/kernel/memory/address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp index 6cf43ba24..24944d15b 100644 --- a/src/core/hle/kernel/memory/address_space_info.cpp +++ b/src/core/hle/kernel/k_address_space_info.cpp | |||
| @@ -2,15 +2,12 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #include <array> | 5 | #include <array> |
| 9 | 6 | ||
| 10 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 11 | #include "core/hle/kernel/memory/address_space_info.h" | 8 | #include "core/hle/kernel/k_address_space_info.h" |
| 12 | 9 | ||
| 13 | namespace Kernel::Memory { | 10 | namespace Kernel { |
| 14 | 11 | ||
| 15 | namespace { | 12 | namespace { |
| 16 | 13 | ||
| @@ -28,20 +25,20 @@ enum : u64 { | |||
| 28 | }; | 25 | }; |
| 29 | 26 | ||
| 30 | // clang-format off | 27 | // clang-format off |
| 31 | constexpr std::array<AddressSpaceInfo, 13> AddressSpaceInfos{{ | 28 | constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{ |
| 32 | { .bit_width = 32, .address = Size_2_MB , .size = Size_1_GB - Size_2_MB , .type = AddressSpaceInfo::Type::Is32Bit, }, | 29 | { .bit_width = 32, .address = Size_2_MB , .size = Size_1_GB - Size_2_MB , .type = KAddressSpaceInfo::Type::MapSmall, }, |
| 33 | { .bit_width = 32, .address = Size_1_GB , .size = Size_4_GB - Size_1_GB , .type = AddressSpaceInfo::Type::Small64Bit, }, | 30 | { .bit_width = 32, .address = Size_1_GB , .size = Size_4_GB - Size_1_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, |
| 34 | { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = AddressSpaceInfo::Type::Heap, }, | 31 | { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = KAddressSpaceInfo::Type::Heap, }, |
| 35 | { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = AddressSpaceInfo::Type::Alias, }, | 32 | { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = KAddressSpaceInfo::Type::Alias, }, |
| 36 | { .bit_width = 36, .address = Size_128_MB, .size = Size_2_GB - Size_128_MB, .type = AddressSpaceInfo::Type::Is32Bit, }, | 33 | { .bit_width = 36, .address = Size_128_MB, .size = Size_2_GB - Size_128_MB, .type = KAddressSpaceInfo::Type::MapSmall, }, |
| 37 | { .bit_width = 36, .address = Size_2_GB , .size = Size_64_GB - Size_2_GB , .type = AddressSpaceInfo::Type::Small64Bit, }, | 34 | { .bit_width = 36, .address = Size_2_GB , .size = Size_64_GB - Size_2_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, |
| 38 | { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Heap, }, | 35 | { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, |
| 39 | { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Alias, }, | 36 | { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Alias, }, |
| 40 | { .bit_width = 39, .address = Size_128_MB, .size = Size_512_GB - Size_128_MB, .type = AddressSpaceInfo::Type::Large64Bit, }, | 37 | { .bit_width = 39, .address = Size_128_MB, .size = Size_512_GB - Size_128_MB, .type = KAddressSpaceInfo::Type::Map39Bit, }, |
| 41 | { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = AddressSpaceInfo::Type::Is32Bit }, | 38 | { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = KAddressSpaceInfo::Type::MapSmall }, |
| 42 | { .bit_width = 39, .address = Invalid , .size = Size_6_GB , .type = AddressSpaceInfo::Type::Heap, }, | 39 | { .bit_width = 39, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, |
| 43 | { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = AddressSpaceInfo::Type::Alias, }, | 40 | { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = KAddressSpaceInfo::Type::Alias, }, |
| 44 | { .bit_width = 39, .address = Invalid , .size = Size_2_GB , .type = AddressSpaceInfo::Type::Stack, }, | 41 | { .bit_width = 39, .address = Invalid , .size = Size_2_GB , .type = KAddressSpaceInfo::Type::Stack, }, |
| 45 | }}; | 42 | }}; |
| 46 | // clang-format on | 43 | // clang-format on |
| 47 | 44 | ||
| @@ -49,7 +46,8 @@ constexpr bool IsAllowedIndexForAddress(std::size_t index) { | |||
| 49 | return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Invalid; | 46 | return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Invalid; |
| 50 | } | 47 | } |
| 51 | 48 | ||
| 52 | using IndexArray = std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)>; | 49 | using IndexArray = |
| 50 | std::array<std::size_t, static_cast<std::size_t>(KAddressSpaceInfo::Type::Count)>; | ||
| 53 | 51 | ||
| 54 | constexpr IndexArray AddressSpaceIndices32Bit{ | 52 | constexpr IndexArray AddressSpaceIndices32Bit{ |
| 55 | 0, 1, 0, 2, 0, 3, | 53 | 0, 1, 0, 2, 0, 3, |
| @@ -63,23 +61,23 @@ constexpr IndexArray AddressSpaceIndices39Bit{ | |||
| 63 | 9, 8, 8, 10, 12, 11, | 61 | 9, 8, 8, 10, 12, 11, |
| 64 | }; | 62 | }; |
| 65 | 63 | ||
| 66 | constexpr bool IsAllowed32BitType(AddressSpaceInfo::Type type) { | 64 | constexpr bool IsAllowed32BitType(KAddressSpaceInfo::Type type) { |
| 67 | return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit && | 65 | return type < KAddressSpaceInfo::Type::Count && type != KAddressSpaceInfo::Type::Map39Bit && |
| 68 | type != AddressSpaceInfo::Type::Stack; | 66 | type != KAddressSpaceInfo::Type::Stack; |
| 69 | } | 67 | } |
| 70 | 68 | ||
| 71 | constexpr bool IsAllowed36BitType(AddressSpaceInfo::Type type) { | 69 | constexpr bool IsAllowed36BitType(KAddressSpaceInfo::Type type) { |
| 72 | return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit && | 70 | return type < KAddressSpaceInfo::Type::Count && type != KAddressSpaceInfo::Type::Map39Bit && |
| 73 | type != AddressSpaceInfo::Type::Stack; | 71 | type != KAddressSpaceInfo::Type::Stack; |
| 74 | } | 72 | } |
| 75 | 73 | ||
| 76 | constexpr bool IsAllowed39BitType(AddressSpaceInfo::Type type) { | 74 | constexpr bool IsAllowed39BitType(KAddressSpaceInfo::Type type) { |
| 77 | return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Small64Bit; | 75 | return type < KAddressSpaceInfo::Type::Count && type != KAddressSpaceInfo::Type::MapLarge; |
| 78 | } | 76 | } |
| 79 | 77 | ||
| 80 | } // namespace | 78 | } // namespace |
| 81 | 79 | ||
| 82 | u64 AddressSpaceInfo::GetAddressSpaceStart(std::size_t width, Type type) { | 80 | u64 KAddressSpaceInfo::GetAddressSpaceStart(std::size_t width, Type type) { |
| 83 | const std::size_t index{static_cast<std::size_t>(type)}; | 81 | const std::size_t index{static_cast<std::size_t>(type)}; |
| 84 | switch (width) { | 82 | switch (width) { |
| 85 | case 32: | 83 | case 32: |
| @@ -99,7 +97,7 @@ u64 AddressSpaceInfo::GetAddressSpaceStart(std::size_t width, Type type) { | |||
| 99 | return 0; | 97 | return 0; |
| 100 | } | 98 | } |
| 101 | 99 | ||
| 102 | std::size_t AddressSpaceInfo::GetAddressSpaceSize(std::size_t width, Type type) { | 100 | std::size_t KAddressSpaceInfo::GetAddressSpaceSize(std::size_t width, Type type) { |
| 103 | const std::size_t index{static_cast<std::size_t>(type)}; | 101 | const std::size_t index{static_cast<std::size_t>(type)}; |
| 104 | switch (width) { | 102 | switch (width) { |
| 105 | case 32: | 103 | case 32: |
| @@ -116,4 +114,4 @@ std::size_t AddressSpaceInfo::GetAddressSpaceSize(std::size_t width, Type type) | |||
| 116 | return 0; | 114 | return 0; |
| 117 | } | 115 | } |
| 118 | 116 | ||
| 119 | } // namespace Kernel::Memory | 117 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/memory/address_space_info.h b/src/core/hle/kernel/k_address_space_info.h index a4e6e91e5..06f31c6d5 100644 --- a/src/core/hle/kernel/memory/address_space_info.h +++ b/src/core/hle/kernel/k_address_space_info.h | |||
| @@ -2,20 +2,17 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #pragma once | 5 | #pragma once |
| 9 | 6 | ||
| 10 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 11 | 8 | ||
| 12 | namespace Kernel::Memory { | 9 | namespace Kernel { |
| 13 | 10 | ||
| 14 | struct AddressSpaceInfo final { | 11 | struct KAddressSpaceInfo final { |
| 15 | enum class Type : u32 { | 12 | enum class Type : u32 { |
| 16 | Is32Bit = 0, | 13 | MapSmall = 0, |
| 17 | Small64Bit = 1, | 14 | MapLarge = 1, |
| 18 | Large64Bit = 2, | 15 | Map39Bit = 2, |
| 19 | Heap = 3, | 16 | Heap = 3, |
| 20 | Stack = 4, | 17 | Stack = 4, |
| 21 | Alias = 5, | 18 | Alias = 5, |
| @@ -31,4 +28,4 @@ struct AddressSpaceInfo final { | |||
| 31 | const Type type{}; | 28 | const Type type{}; |
| 32 | }; | 29 | }; |
| 33 | 30 | ||
| 34 | } // namespace Kernel::Memory | 31 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/memory/memory_block.h b/src/core/hle/kernel/k_memory_block.h index 83acece1e..c5b9c5e85 100644 --- a/src/core/hle/kernel/memory/memory_block.h +++ b/src/core/hle/kernel/k_memory_block.h | |||
| @@ -2,20 +2,17 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #pragma once | 5 | #pragma once |
| 9 | 6 | ||
| 10 | #include "common/alignment.h" | 7 | #include "common/alignment.h" |
| 11 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 12 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 13 | #include "core/hle/kernel/memory/memory_types.h" | 10 | #include "core/hle/kernel/memory_types.h" |
| 14 | #include "core/hle/kernel/svc_types.h" | 11 | #include "core/hle/kernel/svc_types.h" |
| 15 | 12 | ||
| 16 | namespace Kernel::Memory { | 13 | namespace Kernel { |
| 17 | 14 | ||
| 18 | enum class MemoryState : u32 { | 15 | enum class KMemoryState : u32 { |
| 19 | None = 0, | 16 | None = 0, |
| 20 | Mask = 0xFF, | 17 | Mask = 0xFF, |
| 21 | All = ~None, | 18 | All = ~None, |
| @@ -97,31 +94,31 @@ enum class MemoryState : u32 { | |||
| 97 | FlagReferenceCounted | FlagCanDebug, | 94 | FlagReferenceCounted | FlagCanDebug, |
| 98 | CodeOut = static_cast<u32>(Svc::MemoryState::CodeOut) | FlagMapped | FlagReferenceCounted, | 95 | CodeOut = static_cast<u32>(Svc::MemoryState::CodeOut) | FlagMapped | FlagReferenceCounted, |
| 99 | }; | 96 | }; |
| 100 | DECLARE_ENUM_FLAG_OPERATORS(MemoryState); | 97 | DECLARE_ENUM_FLAG_OPERATORS(KMemoryState); |
| 101 | 98 | ||
| 102 | static_assert(static_cast<u32>(MemoryState::Free) == 0x00000000); | 99 | static_assert(static_cast<u32>(KMemoryState::Free) == 0x00000000); |
| 103 | static_assert(static_cast<u32>(MemoryState::Io) == 0x00002001); | 100 | static_assert(static_cast<u32>(KMemoryState::Io) == 0x00002001); |
| 104 | static_assert(static_cast<u32>(MemoryState::Static) == 0x00042002); | 101 | static_assert(static_cast<u32>(KMemoryState::Static) == 0x00042002); |
| 105 | static_assert(static_cast<u32>(MemoryState::Code) == 0x00DC7E03); | 102 | static_assert(static_cast<u32>(KMemoryState::Code) == 0x00DC7E03); |
| 106 | static_assert(static_cast<u32>(MemoryState::CodeData) == 0x03FEBD04); | 103 | static_assert(static_cast<u32>(KMemoryState::CodeData) == 0x03FEBD04); |
| 107 | static_assert(static_cast<u32>(MemoryState::Normal) == 0x037EBD05); | 104 | static_assert(static_cast<u32>(KMemoryState::Normal) == 0x037EBD05); |
| 108 | static_assert(static_cast<u32>(MemoryState::Shared) == 0x00402006); | 105 | static_assert(static_cast<u32>(KMemoryState::Shared) == 0x00402006); |
| 109 | static_assert(static_cast<u32>(MemoryState::AliasCode) == 0x00DD7E08); | 106 | static_assert(static_cast<u32>(KMemoryState::AliasCode) == 0x00DD7E08); |
| 110 | static_assert(static_cast<u32>(MemoryState::AliasCodeData) == 0x03FFBD09); | 107 | static_assert(static_cast<u32>(KMemoryState::AliasCodeData) == 0x03FFBD09); |
| 111 | static_assert(static_cast<u32>(MemoryState::Ipc) == 0x005C3C0A); | 108 | static_assert(static_cast<u32>(KMemoryState::Ipc) == 0x005C3C0A); |
| 112 | static_assert(static_cast<u32>(MemoryState::Stack) == 0x005C3C0B); | 109 | static_assert(static_cast<u32>(KMemoryState::Stack) == 0x005C3C0B); |
| 113 | static_assert(static_cast<u32>(MemoryState::ThreadLocal) == 0x0040200C); | 110 | static_assert(static_cast<u32>(KMemoryState::ThreadLocal) == 0x0040200C); |
| 114 | static_assert(static_cast<u32>(MemoryState::Transferred) == 0x015C3C0D); | 111 | static_assert(static_cast<u32>(KMemoryState::Transferred) == 0x015C3C0D); |
| 115 | static_assert(static_cast<u32>(MemoryState::SharedTransferred) == 0x005C380E); | 112 | static_assert(static_cast<u32>(KMemoryState::SharedTransferred) == 0x005C380E); |
| 116 | static_assert(static_cast<u32>(MemoryState::SharedCode) == 0x0040380F); | 113 | static_assert(static_cast<u32>(KMemoryState::SharedCode) == 0x0040380F); |
| 117 | static_assert(static_cast<u32>(MemoryState::Inaccessible) == 0x00000010); | 114 | static_assert(static_cast<u32>(KMemoryState::Inaccessible) == 0x00000010); |
| 118 | static_assert(static_cast<u32>(MemoryState::NonSecureIpc) == 0x005C3811); | 115 | static_assert(static_cast<u32>(KMemoryState::NonSecureIpc) == 0x005C3811); |
| 119 | static_assert(static_cast<u32>(MemoryState::NonDeviceIpc) == 0x004C2812); | 116 | static_assert(static_cast<u32>(KMemoryState::NonDeviceIpc) == 0x004C2812); |
| 120 | static_assert(static_cast<u32>(MemoryState::Kernel) == 0x00002013); | 117 | static_assert(static_cast<u32>(KMemoryState::Kernel) == 0x00002013); |
| 121 | static_assert(static_cast<u32>(MemoryState::GeneratedCode) == 0x00402214); | 118 | static_assert(static_cast<u32>(KMemoryState::GeneratedCode) == 0x00402214); |
| 122 | static_assert(static_cast<u32>(MemoryState::CodeOut) == 0x00402015); | 119 | static_assert(static_cast<u32>(KMemoryState::CodeOut) == 0x00402015); |
| 123 | 120 | ||
| 124 | enum class MemoryPermission : u8 { | 121 | enum class KMemoryPermission : u8 { |
| 125 | None = 0, | 122 | None = 0, |
| 126 | Mask = static_cast<u8>(~None), | 123 | Mask = static_cast<u8>(~None), |
| 127 | 124 | ||
| @@ -135,9 +132,9 @@ enum class MemoryPermission : u8 { | |||
| 135 | UserMask = static_cast<u8>(Svc::MemoryPermission::Read | Svc::MemoryPermission::Write | | 132 | UserMask = static_cast<u8>(Svc::MemoryPermission::Read | Svc::MemoryPermission::Write | |
| 136 | Svc::MemoryPermission::Execute), | 133 | Svc::MemoryPermission::Execute), |
| 137 | }; | 134 | }; |
| 138 | DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission); | 135 | DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission); |
| 139 | 136 | ||
| 140 | enum class MemoryAttribute : u8 { | 137 | enum class KMemoryAttribute : u8 { |
| 141 | None = 0x00, | 138 | None = 0x00, |
| 142 | Mask = 0x7F, | 139 | Mask = 0x7F, |
| 143 | All = Mask, | 140 | All = Mask, |
| @@ -152,18 +149,18 @@ enum class MemoryAttribute : u8 { | |||
| 152 | LockedAndIpcLocked = Locked | IpcLocked, | 149 | LockedAndIpcLocked = Locked | IpcLocked, |
| 153 | DeviceSharedAndUncached = DeviceShared | Uncached | 150 | DeviceSharedAndUncached = DeviceShared | Uncached |
| 154 | }; | 151 | }; |
| 155 | DECLARE_ENUM_FLAG_OPERATORS(MemoryAttribute); | 152 | DECLARE_ENUM_FLAG_OPERATORS(KMemoryAttribute); |
| 156 | 153 | ||
| 157 | static_assert((static_cast<u8>(MemoryAttribute::Mask) & | 154 | static_assert((static_cast<u8>(KMemoryAttribute::Mask) & |
| 158 | static_cast<u8>(MemoryAttribute::DontCareMask)) == 0); | 155 | static_cast<u8>(KMemoryAttribute::DontCareMask)) == 0); |
| 159 | 156 | ||
| 160 | struct MemoryInfo { | 157 | struct KMemoryInfo { |
| 161 | VAddr addr{}; | 158 | VAddr addr{}; |
| 162 | std::size_t size{}; | 159 | std::size_t size{}; |
| 163 | MemoryState state{}; | 160 | KMemoryState state{}; |
| 164 | MemoryPermission perm{}; | 161 | KMemoryPermission perm{}; |
| 165 | MemoryAttribute attribute{}; | 162 | KMemoryAttribute attribute{}; |
| 166 | MemoryPermission original_perm{}; | 163 | KMemoryPermission original_perm{}; |
| 167 | u16 ipc_lock_count{}; | 164 | u16 ipc_lock_count{}; |
| 168 | u16 device_use_count{}; | 165 | u16 device_use_count{}; |
| 169 | 166 | ||
| @@ -171,9 +168,9 @@ struct MemoryInfo { | |||
| 171 | return { | 168 | return { |
| 172 | addr, | 169 | addr, |
| 173 | size, | 170 | size, |
| 174 | static_cast<Svc::MemoryState>(state & MemoryState::Mask), | 171 | static_cast<Svc::MemoryState>(state & KMemoryState::Mask), |
| 175 | static_cast<Svc::MemoryAttribute>(attribute & MemoryAttribute::Mask), | 172 | static_cast<Svc::MemoryAttribute>(attribute & KMemoryAttribute::Mask), |
| 176 | static_cast<Svc::MemoryPermission>(perm & MemoryPermission::UserMask), | 173 | static_cast<Svc::MemoryPermission>(perm & KMemoryPermission::UserMask), |
| 177 | ipc_lock_count, | 174 | ipc_lock_count, |
| 178 | device_use_count, | 175 | device_use_count, |
| 179 | }; | 176 | }; |
| @@ -196,21 +193,21 @@ struct MemoryInfo { | |||
| 196 | } | 193 | } |
| 197 | }; | 194 | }; |
| 198 | 195 | ||
| 199 | class MemoryBlock final { | 196 | class KMemoryBlock final { |
| 200 | friend class MemoryBlockManager; | 197 | friend class KMemoryBlockManager; |
| 201 | 198 | ||
| 202 | private: | 199 | private: |
| 203 | VAddr addr{}; | 200 | VAddr addr{}; |
| 204 | std::size_t num_pages{}; | 201 | std::size_t num_pages{}; |
| 205 | MemoryState state{MemoryState::None}; | 202 | KMemoryState state{KMemoryState::None}; |
| 206 | u16 ipc_lock_count{}; | 203 | u16 ipc_lock_count{}; |
| 207 | u16 device_use_count{}; | 204 | u16 device_use_count{}; |
| 208 | MemoryPermission perm{MemoryPermission::None}; | 205 | KMemoryPermission perm{KMemoryPermission::None}; |
| 209 | MemoryPermission original_perm{MemoryPermission::None}; | 206 | KMemoryPermission original_perm{KMemoryPermission::None}; |
| 210 | MemoryAttribute attribute{MemoryAttribute::None}; | 207 | KMemoryAttribute attribute{KMemoryAttribute::None}; |
| 211 | 208 | ||
| 212 | public: | 209 | public: |
| 213 | static constexpr int Compare(const MemoryBlock& lhs, const MemoryBlock& rhs) { | 210 | static constexpr int Compare(const KMemoryBlock& lhs, const KMemoryBlock& rhs) { |
| 214 | if (lhs.GetAddress() < rhs.GetAddress()) { | 211 | if (lhs.GetAddress() < rhs.GetAddress()) { |
| 215 | return -1; | 212 | return -1; |
| 216 | } else if (lhs.GetAddress() <= rhs.GetLastAddress()) { | 213 | } else if (lhs.GetAddress() <= rhs.GetLastAddress()) { |
| @@ -221,9 +218,9 @@ public: | |||
| 221 | } | 218 | } |
| 222 | 219 | ||
| 223 | public: | 220 | public: |
| 224 | constexpr MemoryBlock() = default; | 221 | constexpr KMemoryBlock() = default; |
| 225 | constexpr MemoryBlock(VAddr addr_, std::size_t num_pages_, MemoryState state_, | 222 | constexpr KMemoryBlock(VAddr addr_, std::size_t num_pages_, KMemoryState state_, |
| 226 | MemoryPermission perm_, MemoryAttribute attribute_) | 223 | KMemoryPermission perm_, KMemoryAttribute attribute_) |
| 227 | : addr{addr_}, num_pages(num_pages_), state{state_}, perm{perm_}, attribute{attribute_} {} | 224 | : addr{addr_}, num_pages(num_pages_), state{state_}, perm{perm_}, attribute{attribute_} {} |
| 228 | 225 | ||
| 229 | constexpr VAddr GetAddress() const { | 226 | constexpr VAddr GetAddress() const { |
| @@ -246,40 +243,40 @@ public: | |||
| 246 | return GetEndAddress() - 1; | 243 | return GetEndAddress() - 1; |
| 247 | } | 244 | } |
| 248 | 245 | ||
| 249 | constexpr MemoryInfo GetMemoryInfo() const { | 246 | constexpr KMemoryInfo GetMemoryInfo() const { |
| 250 | return { | 247 | return { |
| 251 | GetAddress(), GetSize(), state, perm, | 248 | GetAddress(), GetSize(), state, perm, |
| 252 | attribute, original_perm, ipc_lock_count, device_use_count, | 249 | attribute, original_perm, ipc_lock_count, device_use_count, |
| 253 | }; | 250 | }; |
| 254 | } | 251 | } |
| 255 | 252 | ||
| 256 | void ShareToDevice(MemoryPermission /*new_perm*/) { | 253 | void ShareToDevice(KMemoryPermission /*new_perm*/) { |
| 257 | ASSERT((attribute & MemoryAttribute::DeviceShared) == MemoryAttribute::DeviceShared || | 254 | ASSERT((attribute & KMemoryAttribute::DeviceShared) == KMemoryAttribute::DeviceShared || |
| 258 | device_use_count == 0); | 255 | device_use_count == 0); |
| 259 | attribute |= MemoryAttribute::DeviceShared; | 256 | attribute |= KMemoryAttribute::DeviceShared; |
| 260 | const u16 new_use_count{++device_use_count}; | 257 | const u16 new_use_count{++device_use_count}; |
| 261 | ASSERT(new_use_count > 0); | 258 | ASSERT(new_use_count > 0); |
| 262 | } | 259 | } |
| 263 | 260 | ||
| 264 | void UnshareToDevice(MemoryPermission /*new_perm*/) { | 261 | void UnshareToDevice(KMemoryPermission /*new_perm*/) { |
| 265 | ASSERT((attribute & MemoryAttribute::DeviceShared) == MemoryAttribute::DeviceShared); | 262 | ASSERT((attribute & KMemoryAttribute::DeviceShared) == KMemoryAttribute::DeviceShared); |
| 266 | const u16 prev_use_count{device_use_count--}; | 263 | const u16 prev_use_count{device_use_count--}; |
| 267 | ASSERT(prev_use_count > 0); | 264 | ASSERT(prev_use_count > 0); |
| 268 | if (prev_use_count == 1) { | 265 | if (prev_use_count == 1) { |
| 269 | attribute &= ~MemoryAttribute::DeviceShared; | 266 | attribute &= ~KMemoryAttribute::DeviceShared; |
| 270 | } | 267 | } |
| 271 | } | 268 | } |
| 272 | 269 | ||
| 273 | private: | 270 | private: |
| 274 | constexpr bool HasProperties(MemoryState s, MemoryPermission p, MemoryAttribute a) const { | 271 | constexpr bool HasProperties(KMemoryState s, KMemoryPermission p, KMemoryAttribute a) const { |
| 275 | constexpr MemoryAttribute AttributeIgnoreMask{MemoryAttribute::DontCareMask | | 272 | constexpr KMemoryAttribute AttributeIgnoreMask{KMemoryAttribute::DontCareMask | |
| 276 | MemoryAttribute::IpcLocked | | 273 | KMemoryAttribute::IpcLocked | |
| 277 | MemoryAttribute::DeviceShared}; | 274 | KMemoryAttribute::DeviceShared}; |
| 278 | return state == s && perm == p && | 275 | return state == s && perm == p && |
| 279 | (attribute | AttributeIgnoreMask) == (a | AttributeIgnoreMask); | 276 | (attribute | AttributeIgnoreMask) == (a | AttributeIgnoreMask); |
| 280 | } | 277 | } |
| 281 | 278 | ||
| 282 | constexpr bool HasSameProperties(const MemoryBlock& rhs) const { | 279 | constexpr bool HasSameProperties(const KMemoryBlock& rhs) const { |
| 283 | return state == rhs.state && perm == rhs.perm && original_perm == rhs.original_perm && | 280 | return state == rhs.state && perm == rhs.perm && original_perm == rhs.original_perm && |
| 284 | attribute == rhs.attribute && ipc_lock_count == rhs.ipc_lock_count && | 281 | attribute == rhs.attribute && ipc_lock_count == rhs.ipc_lock_count && |
| 285 | device_use_count == rhs.device_use_count; | 282 | device_use_count == rhs.device_use_count; |
| @@ -296,25 +293,25 @@ private: | |||
| 296 | num_pages += count; | 293 | num_pages += count; |
| 297 | } | 294 | } |
| 298 | 295 | ||
| 299 | constexpr void Update(MemoryState new_state, MemoryPermission new_perm, | 296 | constexpr void Update(KMemoryState new_state, KMemoryPermission new_perm, |
| 300 | MemoryAttribute new_attribute) { | 297 | KMemoryAttribute new_attribute) { |
| 301 | ASSERT(original_perm == MemoryPermission::None); | 298 | ASSERT(original_perm == KMemoryPermission::None); |
| 302 | ASSERT((attribute & MemoryAttribute::IpcLocked) == MemoryAttribute::None); | 299 | ASSERT((attribute & KMemoryAttribute::IpcLocked) == KMemoryAttribute::None); |
| 303 | 300 | ||
| 304 | state = new_state; | 301 | state = new_state; |
| 305 | perm = new_perm; | 302 | perm = new_perm; |
| 306 | 303 | ||
| 307 | attribute = static_cast<MemoryAttribute>( | 304 | attribute = static_cast<KMemoryAttribute>( |
| 308 | new_attribute | | 305 | new_attribute | |
| 309 | (attribute & (MemoryAttribute::IpcLocked | MemoryAttribute::DeviceShared))); | 306 | (attribute & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared))); |
| 310 | } | 307 | } |
| 311 | 308 | ||
| 312 | constexpr MemoryBlock Split(VAddr split_addr) { | 309 | constexpr KMemoryBlock Split(VAddr split_addr) { |
| 313 | ASSERT(GetAddress() < split_addr); | 310 | ASSERT(GetAddress() < split_addr); |
| 314 | ASSERT(Contains(split_addr)); | 311 | ASSERT(Contains(split_addr)); |
| 315 | ASSERT(Common::IsAligned(split_addr, PageSize)); | 312 | ASSERT(Common::IsAligned(split_addr, PageSize)); |
| 316 | 313 | ||
| 317 | MemoryBlock block; | 314 | KMemoryBlock block; |
| 318 | block.addr = addr; | 315 | block.addr = addr; |
| 319 | block.num_pages = (split_addr - GetAddress()) / PageSize; | 316 | block.num_pages = (split_addr - GetAddress()) / PageSize; |
| 320 | block.state = state; | 317 | block.state = state; |
| @@ -330,6 +327,6 @@ private: | |||
| 330 | return block; | 327 | return block; |
| 331 | } | 328 | } |
| 332 | }; | 329 | }; |
| 333 | static_assert(std::is_trivially_destructible<MemoryBlock>::value); | 330 | static_assert(std::is_trivially_destructible<KMemoryBlock>::value); |
| 334 | 331 | ||
| 335 | } // namespace Kernel::Memory | 332 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/memory/memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp index 0732fa5a1..4a2d88008 100644 --- a/src/core/hle/kernel/memory/memory_block_manager.cpp +++ b/src/core/hle/kernel/k_memory_block_manager.cpp | |||
| @@ -2,19 +2,19 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/hle/kernel/memory/memory_block_manager.h" | 5 | #include "core/hle/kernel/k_memory_block_manager.h" |
| 6 | #include "core/hle/kernel/memory/memory_types.h" | 6 | #include "core/hle/kernel/memory_types.h" |
| 7 | 7 | ||
| 8 | namespace Kernel::Memory { | 8 | namespace Kernel { |
| 9 | 9 | ||
| 10 | MemoryBlockManager::MemoryBlockManager(VAddr start_addr, VAddr end_addr) | 10 | KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr, VAddr end_addr) |
| 11 | : start_addr{start_addr}, end_addr{end_addr} { | 11 | : start_addr{start_addr}, end_addr{end_addr} { |
| 12 | const u64 num_pages{(end_addr - start_addr) / PageSize}; | 12 | const u64 num_pages{(end_addr - start_addr) / PageSize}; |
| 13 | memory_block_tree.emplace_back(start_addr, num_pages, MemoryState::Free, MemoryPermission::None, | 13 | memory_block_tree.emplace_back(start_addr, num_pages, KMemoryState::Free, |
| 14 | MemoryAttribute::None); | 14 | KMemoryPermission::None, KMemoryAttribute::None); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | MemoryBlockManager::iterator MemoryBlockManager::FindIterator(VAddr addr) { | 17 | KMemoryBlockManager::iterator KMemoryBlockManager::FindIterator(VAddr addr) { |
| 18 | auto node{memory_block_tree.begin()}; | 18 | auto node{memory_block_tree.begin()}; |
| 19 | while (node != end()) { | 19 | while (node != end()) { |
| 20 | const VAddr end_addr{node->GetNumPages() * PageSize + node->GetAddress()}; | 20 | const VAddr end_addr{node->GetNumPages() * PageSize + node->GetAddress()}; |
| @@ -26,9 +26,9 @@ MemoryBlockManager::iterator MemoryBlockManager::FindIterator(VAddr addr) { | |||
| 26 | return end(); | 26 | return end(); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | VAddr MemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_num_pages, | 29 | VAddr KMemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_num_pages, |
| 30 | std::size_t num_pages, std::size_t align, std::size_t offset, | 30 | std::size_t num_pages, std::size_t align, |
| 31 | std::size_t guard_pages) { | 31 | std::size_t offset, std::size_t guard_pages) { |
| 32 | if (num_pages == 0) { | 32 | if (num_pages == 0) { |
| 33 | return {}; | 33 | return {}; |
| 34 | } | 34 | } |
| @@ -41,7 +41,7 @@ VAddr MemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_nu | |||
| 41 | break; | 41 | break; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | if (info.state != MemoryState::Free) { | 44 | if (info.state != KMemoryState::Free) { |
| 45 | continue; | 45 | continue; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| @@ -63,17 +63,17 @@ VAddr MemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_nu | |||
| 63 | return {}; | 63 | return {}; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState prev_state, | 66 | void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState prev_state, |
| 67 | MemoryPermission prev_perm, MemoryAttribute prev_attribute, | 67 | KMemoryPermission prev_perm, KMemoryAttribute prev_attribute, |
| 68 | MemoryState state, MemoryPermission perm, | 68 | KMemoryState state, KMemoryPermission perm, |
| 69 | MemoryAttribute attribute) { | 69 | KMemoryAttribute attribute) { |
| 70 | const VAddr end_addr{addr + num_pages * PageSize}; | 70 | const VAddr end_addr{addr + num_pages * PageSize}; |
| 71 | iterator node{memory_block_tree.begin()}; | 71 | iterator node{memory_block_tree.begin()}; |
| 72 | 72 | ||
| 73 | prev_attribute |= MemoryAttribute::IpcAndDeviceMapped; | 73 | prev_attribute |= KMemoryAttribute::IpcAndDeviceMapped; |
| 74 | 74 | ||
| 75 | while (node != memory_block_tree.end()) { | 75 | while (node != memory_block_tree.end()) { |
| 76 | MemoryBlock* block{&(*node)}; | 76 | KMemoryBlock* block{&(*node)}; |
| 77 | iterator next_node{std::next(node)}; | 77 | iterator next_node{std::next(node)}; |
| 78 | const VAddr cur_addr{block->GetAddress()}; | 78 | const VAddr cur_addr{block->GetAddress()}; |
| 79 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; | 79 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; |
| @@ -106,13 +106,13 @@ void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState p | |||
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState state, | 109 | void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState state, |
| 110 | MemoryPermission perm, MemoryAttribute attribute) { | 110 | KMemoryPermission perm, KMemoryAttribute attribute) { |
| 111 | const VAddr end_addr{addr + num_pages * PageSize}; | 111 | const VAddr end_addr{addr + num_pages * PageSize}; |
| 112 | iterator node{memory_block_tree.begin()}; | 112 | iterator node{memory_block_tree.begin()}; |
| 113 | 113 | ||
| 114 | while (node != memory_block_tree.end()) { | 114 | while (node != memory_block_tree.end()) { |
| 115 | MemoryBlock* block{&(*node)}; | 115 | KMemoryBlock* block{&(*node)}; |
| 116 | iterator next_node{std::next(node)}; | 116 | iterator next_node{std::next(node)}; |
| 117 | const VAddr cur_addr{block->GetAddress()}; | 117 | const VAddr cur_addr{block->GetAddress()}; |
| 118 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; | 118 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; |
| @@ -141,13 +141,13 @@ void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState s | |||
| 141 | } | 141 | } |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | void MemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, | 144 | void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, |
| 145 | MemoryPermission perm) { | 145 | KMemoryPermission perm) { |
| 146 | const VAddr end_addr{addr + num_pages * PageSize}; | 146 | const VAddr end_addr{addr + num_pages * PageSize}; |
| 147 | iterator node{memory_block_tree.begin()}; | 147 | iterator node{memory_block_tree.begin()}; |
| 148 | 148 | ||
| 149 | while (node != memory_block_tree.end()) { | 149 | while (node != memory_block_tree.end()) { |
| 150 | MemoryBlock* block{&(*node)}; | 150 | KMemoryBlock* block{&(*node)}; |
| 151 | iterator next_node{std::next(node)}; | 151 | iterator next_node{std::next(node)}; |
| 152 | const VAddr cur_addr{block->GetAddress()}; | 152 | const VAddr cur_addr{block->GetAddress()}; |
| 153 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; | 153 | const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; |
| @@ -176,9 +176,9 @@ void MemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc& | |||
| 176 | } | 176 | } |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | void MemoryBlockManager::IterateForRange(VAddr start, VAddr end, IterateFunc&& func) { | 179 | void KMemoryBlockManager::IterateForRange(VAddr start, VAddr end, IterateFunc&& func) { |
| 180 | const_iterator it{FindIterator(start)}; | 180 | const_iterator it{FindIterator(start)}; |
| 181 | MemoryInfo info{}; | 181 | KMemoryInfo info{}; |
| 182 | do { | 182 | do { |
| 183 | info = it->GetMemoryInfo(); | 183 | info = it->GetMemoryInfo(); |
| 184 | func(info); | 184 | func(info); |
| @@ -186,8 +186,8 @@ void MemoryBlockManager::IterateForRange(VAddr start, VAddr end, IterateFunc&& f | |||
| 186 | } while (info.addr + info.size - 1 < end - 1 && it != cend()); | 186 | } while (info.addr + info.size - 1 < end - 1 && it != cend()); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) { | 189 | void KMemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) { |
| 190 | MemoryBlock* block{&(*it)}; | 190 | KMemoryBlock* block{&(*it)}; |
| 191 | 191 | ||
| 192 | auto EraseIt = [&](const iterator it_to_erase) { | 192 | auto EraseIt = [&](const iterator it_to_erase) { |
| 193 | if (next_it == it_to_erase) { | 193 | if (next_it == it_to_erase) { |
| @@ -197,7 +197,7 @@ void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) { | |||
| 197 | }; | 197 | }; |
| 198 | 198 | ||
| 199 | if (it != memory_block_tree.begin()) { | 199 | if (it != memory_block_tree.begin()) { |
| 200 | MemoryBlock* prev{&(*std::prev(it))}; | 200 | KMemoryBlock* prev{&(*std::prev(it))}; |
| 201 | 201 | ||
| 202 | if (block->HasSameProperties(*prev)) { | 202 | if (block->HasSameProperties(*prev)) { |
| 203 | const iterator prev_it{std::prev(it)}; | 203 | const iterator prev_it{std::prev(it)}; |
| @@ -211,7 +211,7 @@ void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) { | |||
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | if (it != cend()) { | 213 | if (it != cend()) { |
| 214 | const MemoryBlock* const next{&(*std::next(it))}; | 214 | const KMemoryBlock* const next{&(*std::next(it))}; |
| 215 | 215 | ||
| 216 | if (block->HasSameProperties(*next)) { | 216 | if (block->HasSameProperties(*next)) { |
| 217 | block->Add(next->GetNumPages()); | 217 | block->Add(next->GetNumPages()); |
| @@ -220,4 +220,4 @@ void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) { | |||
| 220 | } | 220 | } |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | } // namespace Kernel::Memory | 223 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/memory/memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h index f57d1bbcc..e11cc70c8 100644 --- a/src/core/hle/kernel/memory/memory_block_manager.h +++ b/src/core/hle/kernel/k_memory_block_manager.h | |||
| @@ -8,18 +8,18 @@ | |||
| 8 | #include <list> | 8 | #include <list> |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/hle/kernel/memory/memory_block.h" | 11 | #include "core/hle/kernel/k_memory_block.h" |
| 12 | 12 | ||
| 13 | namespace Kernel::Memory { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | class MemoryBlockManager final { | 15 | class KMemoryBlockManager final { |
| 16 | public: | 16 | public: |
| 17 | using MemoryBlockTree = std::list<MemoryBlock>; | 17 | using MemoryBlockTree = std::list<KMemoryBlock>; |
| 18 | using iterator = MemoryBlockTree::iterator; | 18 | using iterator = MemoryBlockTree::iterator; |
| 19 | using const_iterator = MemoryBlockTree::const_iterator; | 19 | using const_iterator = MemoryBlockTree::const_iterator; |
| 20 | 20 | ||
| 21 | public: | 21 | public: |
| 22 | MemoryBlockManager(VAddr start_addr, VAddr end_addr); | 22 | KMemoryBlockManager(VAddr start_addr, VAddr end_addr); |
| 23 | 23 | ||
| 24 | iterator end() { | 24 | iterator end() { |
| 25 | return memory_block_tree.end(); | 25 | return memory_block_tree.end(); |
| @@ -36,21 +36,22 @@ public: | |||
| 36 | VAddr FindFreeArea(VAddr region_start, std::size_t region_num_pages, std::size_t num_pages, | 36 | VAddr FindFreeArea(VAddr region_start, std::size_t region_num_pages, std::size_t num_pages, |
| 37 | std::size_t align, std::size_t offset, std::size_t guard_pages); | 37 | std::size_t align, std::size_t offset, std::size_t guard_pages); |
| 38 | 38 | ||
| 39 | void Update(VAddr addr, std::size_t num_pages, MemoryState prev_state, | 39 | void Update(VAddr addr, std::size_t num_pages, KMemoryState prev_state, |
| 40 | MemoryPermission prev_perm, MemoryAttribute prev_attribute, MemoryState state, | 40 | KMemoryPermission prev_perm, KMemoryAttribute prev_attribute, KMemoryState state, |
| 41 | MemoryPermission perm, MemoryAttribute attribute); | 41 | KMemoryPermission perm, KMemoryAttribute attribute); |
| 42 | 42 | ||
| 43 | void Update(VAddr addr, std::size_t num_pages, MemoryState state, | 43 | void Update(VAddr addr, std::size_t num_pages, KMemoryState state, |
| 44 | MemoryPermission perm = MemoryPermission::None, | 44 | KMemoryPermission perm = KMemoryPermission::None, |
| 45 | MemoryAttribute attribute = MemoryAttribute::None); | 45 | KMemoryAttribute attribute = KMemoryAttribute::None); |
| 46 | 46 | ||
| 47 | using LockFunc = std::function<void(iterator, MemoryPermission)>; | 47 | using LockFunc = std::function<void(iterator, KMemoryPermission)>; |
| 48 | void UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, MemoryPermission perm); | 48 | void UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, |
| 49 | KMemoryPermission perm); | ||
| 49 | 50 | ||
| 50 | using IterateFunc = std::function<void(const MemoryInfo&)>; | 51 | using IterateFunc = std::function<void(const KMemoryInfo&)>; |
| 51 | void IterateForRange(VAddr start, VAddr end, IterateFunc&& func); | 52 | void IterateForRange(VAddr start, VAddr end, IterateFunc&& func); |
| 52 | 53 | ||
| 53 | MemoryBlock& FindBlock(VAddr addr) { | 54 | KMemoryBlock& FindBlock(VAddr addr) { |
| 54 | return *FindIterator(addr); | 55 | return *FindIterator(addr); |
| 55 | } | 56 | } |
| 56 | 57 | ||
| @@ -63,4 +64,4 @@ private: | |||
| 63 | MemoryBlockTree memory_block_tree; | 64 | MemoryBlockTree memory_block_tree; |
| 64 | }; | 65 | }; |
| 65 | 66 | ||
| 66 | } // namespace Kernel::Memory | 67 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/memory/memory_layout.h b/src/core/hle/kernel/k_memory_layout.h index c7c0b2f49..0821d2d8c 100644 --- a/src/core/hle/kernel/memory/memory_layout.h +++ b/src/core/hle/kernel/k_memory_layout.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "core/device_memory.h" | 8 | #include "core/device_memory.h" |
| 9 | 9 | ||
| 10 | namespace Kernel::Memory { | 10 | namespace Kernel { |
| 11 | 11 | ||
| 12 | constexpr std::size_t KernelAslrAlignment = 2 * 1024 * 1024; | 12 | constexpr std::size_t KernelAslrAlignment = 2 * 1024 * 1024; |
| 13 | constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39; | 13 | constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39; |
| @@ -27,8 +27,8 @@ constexpr bool IsKernelAddress(VAddr address) { | |||
| 27 | return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; | 27 | return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | class MemoryRegion final { | 30 | class KMemoryRegion final { |
| 31 | friend class MemoryLayout; | 31 | friend class KMemoryLayout; |
| 32 | 32 | ||
| 33 | public: | 33 | public: |
| 34 | constexpr PAddr StartAddress() const { | 34 | constexpr PAddr StartAddress() const { |
| @@ -40,29 +40,29 @@ public: | |||
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | private: | 42 | private: |
| 43 | constexpr MemoryRegion() = default; | 43 | constexpr KMemoryRegion() = default; |
| 44 | constexpr MemoryRegion(PAddr start_address, PAddr end_address) | 44 | constexpr KMemoryRegion(PAddr start_address, PAddr end_address) |
| 45 | : start_address{start_address}, end_address{end_address} {} | 45 | : start_address{start_address}, end_address{end_address} {} |
| 46 | 46 | ||
| 47 | const PAddr start_address{}; | 47 | const PAddr start_address{}; |
| 48 | const PAddr end_address{}; | 48 | const PAddr end_address{}; |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | class MemoryLayout final { | 51 | class KMemoryLayout final { |
| 52 | public: | 52 | public: |
| 53 | constexpr const MemoryRegion& Application() const { | 53 | constexpr const KMemoryRegion& Application() const { |
| 54 | return application; | 54 | return application; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | constexpr const MemoryRegion& Applet() const { | 57 | constexpr const KMemoryRegion& Applet() const { |
| 58 | return applet; | 58 | return applet; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | constexpr const MemoryRegion& System() const { | 61 | constexpr const KMemoryRegion& System() const { |
| 62 | return system; | 62 | return system; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static constexpr MemoryLayout GetDefaultLayout() { | 65 | static constexpr KMemoryLayout GetDefaultLayout() { |
| 66 | constexpr std::size_t application_size{0xcd500000}; | 66 | constexpr std::size_t application_size{0xcd500000}; |
| 67 | constexpr std::size_t applet_size{0x1fb00000}; | 67 | constexpr std::size_t applet_size{0x1fb00000}; |
| 68 | constexpr PAddr application_start_address{Core::DramMemoryMap::End - application_size}; | 68 | constexpr PAddr application_start_address{Core::DramMemoryMap::End - application_size}; |
| @@ -76,15 +76,15 @@ public: | |||
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | private: | 78 | private: |
| 79 | constexpr MemoryLayout(PAddr application_start_address, std::size_t application_size, | 79 | constexpr KMemoryLayout(PAddr application_start_address, std::size_t application_size, |
| 80 | PAddr applet_start_address, std::size_t applet_size, | 80 | PAddr applet_start_address, std::size_t applet_size, |
| 81 | PAddr system_start_address, std::size_t system_size) | 81 | PAddr system_start_address, std::size_t system_size) |
| 82 | : application{application_start_address, application_size}, | 82 | : application{application_start_address, application_size}, |
| 83 | applet{applet_start_address, applet_size}, system{system_start_address, system_size} {} | 83 | applet{applet_start_address, applet_size}, system{system_start_address, system_size} {} |
| 84 | 84 | ||
| 85 | const MemoryRegion application; | 85 | const KMemoryRegion application; |
| 86 | const MemoryRegion applet; | 86 | const KMemoryRegion applet; |
| 87 | const MemoryRegion system; | 87 | const KMemoryRegion system; |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | } // namespace Kernel::Memory | 90 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/memory/memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index 77f135cdc..9027602bf 100644 --- a/src/core/hle/kernel/memory/memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp | |||
| @@ -8,20 +8,20 @@ | |||
| 8 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/scope_exit.h" | 10 | #include "common/scope_exit.h" |
| 11 | #include "core/hle/kernel/memory/memory_manager.h" | 11 | #include "core/hle/kernel/k_memory_manager.h" |
| 12 | #include "core/hle/kernel/memory/page_linked_list.h" | 12 | #include "core/hle/kernel/k_page_linked_list.h" |
| 13 | #include "core/hle/kernel/svc_results.h" | 13 | #include "core/hle/kernel/svc_results.h" |
| 14 | 14 | ||
| 15 | namespace Kernel::Memory { | 15 | namespace Kernel { |
| 16 | 16 | ||
| 17 | std::size_t MemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) { | 17 | std::size_t KMemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) { |
| 18 | const auto size{end_address - start_address}; | 18 | const auto size{end_address - start_address}; |
| 19 | 19 | ||
| 20 | // Calculate metadata sizes | 20 | // Calculate metadata sizes |
| 21 | const auto ref_count_size{(size / PageSize) * sizeof(u16)}; | 21 | const auto ref_count_size{(size / PageSize) * sizeof(u16)}; |
| 22 | const auto optimize_map_size{(Common::AlignUp((size / PageSize), 64) / 64) * sizeof(u64)}; | 22 | const auto optimize_map_size{(Common::AlignUp((size / PageSize), 64) / 64) * sizeof(u64)}; |
| 23 | const auto manager_size{Common::AlignUp(optimize_map_size + ref_count_size, PageSize)}; | 23 | const auto manager_size{Common::AlignUp(optimize_map_size + ref_count_size, PageSize)}; |
| 24 | const auto page_heap_size{PageHeap::CalculateMetadataOverheadSize(size)}; | 24 | const auto page_heap_size{KPageHeap::CalculateManagementOverheadSize(size)}; |
| 25 | const auto total_metadata_size{manager_size + page_heap_size}; | 25 | const auto total_metadata_size{manager_size + page_heap_size}; |
| 26 | ASSERT(manager_size <= total_metadata_size); | 26 | ASSERT(manager_size <= total_metadata_size); |
| 27 | ASSERT(Common::IsAligned(total_metadata_size, PageSize)); | 27 | ASSERT(Common::IsAligned(total_metadata_size, PageSize)); |
| @@ -41,29 +41,30 @@ std::size_t MemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u6 | |||
| 41 | return total_metadata_size; | 41 | return total_metadata_size; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | void MemoryManager::InitializeManager(Pool pool, u64 start_address, u64 end_address) { | 44 | void KMemoryManager::InitializeManager(Pool pool, u64 start_address, u64 end_address) { |
| 45 | ASSERT(pool < Pool::Count); | 45 | ASSERT(pool < Pool::Count); |
| 46 | managers[static_cast<std::size_t>(pool)].Initialize(pool, start_address, end_address); | 46 | managers[static_cast<std::size_t>(pool)].Initialize(pool, start_address, end_address); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | VAddr MemoryManager::AllocateContinuous(std::size_t num_pages, std::size_t align_pages, Pool pool, | 49 | VAddr KMemoryManager::AllocateAndOpenContinuous(std::size_t num_pages, std::size_t align_pages, |
| 50 | Direction dir) { | 50 | u32 option) { |
| 51 | // Early return if we're allocating no pages | 51 | // Early return if we're allocating no pages |
| 52 | if (num_pages == 0) { | 52 | if (num_pages == 0) { |
| 53 | return {}; | 53 | return {}; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | // Lock the pool that we're allocating from | 56 | // Lock the pool that we're allocating from |
| 57 | const auto [pool, dir] = DecodeOption(option); | ||
| 57 | const auto pool_index{static_cast<std::size_t>(pool)}; | 58 | const auto pool_index{static_cast<std::size_t>(pool)}; |
| 58 | std::lock_guard lock{pool_locks[pool_index]}; | 59 | std::lock_guard lock{pool_locks[pool_index]}; |
| 59 | 60 | ||
| 60 | // Choose a heap based on our page size request | 61 | // Choose a heap based on our page size request |
| 61 | const s32 heap_index{PageHeap::GetAlignedBlockIndex(num_pages, align_pages)}; | 62 | const s32 heap_index{KPageHeap::GetAlignedBlockIndex(num_pages, align_pages)}; |
| 62 | 63 | ||
| 63 | // Loop, trying to iterate from each block | 64 | // Loop, trying to iterate from each block |
| 64 | // TODO (bunnei): Support multiple managers | 65 | // TODO (bunnei): Support multiple managers |
| 65 | Impl& chosen_manager{managers[pool_index]}; | 66 | Impl& chosen_manager{managers[pool_index]}; |
| 66 | VAddr allocated_block{chosen_manager.AllocateBlock(heap_index)}; | 67 | VAddr allocated_block{chosen_manager.AllocateBlock(heap_index, false)}; |
| 67 | 68 | ||
| 68 | // If we failed to allocate, quit now | 69 | // If we failed to allocate, quit now |
| 69 | if (!allocated_block) { | 70 | if (!allocated_block) { |
| @@ -71,7 +72,7 @@ VAddr MemoryManager::AllocateContinuous(std::size_t num_pages, std::size_t align | |||
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | // If we allocated more than we need, free some | 74 | // If we allocated more than we need, free some |
| 74 | const auto allocated_pages{PageHeap::GetBlockNumPages(heap_index)}; | 75 | const auto allocated_pages{KPageHeap::GetBlockNumPages(heap_index)}; |
| 75 | if (allocated_pages > num_pages) { | 76 | if (allocated_pages > num_pages) { |
| 76 | chosen_manager.Free(allocated_block + num_pages * PageSize, allocated_pages - num_pages); | 77 | chosen_manager.Free(allocated_block + num_pages * PageSize, allocated_pages - num_pages); |
| 77 | } | 78 | } |
| @@ -79,8 +80,8 @@ VAddr MemoryManager::AllocateContinuous(std::size_t num_pages, std::size_t align | |||
| 79 | return allocated_block; | 80 | return allocated_block; |
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pages, Pool pool, | 83 | ResultCode KMemoryManager::Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, |
| 83 | Direction dir) { | 84 | Direction dir) { |
| 84 | ASSERT(page_list.GetNumPages() == 0); | 85 | ASSERT(page_list.GetNumPages() == 0); |
| 85 | 86 | ||
| 86 | // Early return if we're allocating no pages | 87 | // Early return if we're allocating no pages |
| @@ -93,7 +94,7 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa | |||
| 93 | std::lock_guard lock{pool_locks[pool_index]}; | 94 | std::lock_guard lock{pool_locks[pool_index]}; |
| 94 | 95 | ||
| 95 | // Choose a heap based on our page size request | 96 | // Choose a heap based on our page size request |
| 96 | const s32 heap_index{PageHeap::GetBlockIndex(num_pages)}; | 97 | const s32 heap_index{KPageHeap::GetBlockIndex(num_pages)}; |
| 97 | if (heap_index < 0) { | 98 | if (heap_index < 0) { |
| 98 | return ResultOutOfMemory; | 99 | return ResultOutOfMemory; |
| 99 | } | 100 | } |
| @@ -112,11 +113,11 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa | |||
| 112 | 113 | ||
| 113 | // Keep allocating until we've allocated all our pages | 114 | // Keep allocating until we've allocated all our pages |
| 114 | for (s32 index{heap_index}; index >= 0 && num_pages > 0; index--) { | 115 | for (s32 index{heap_index}; index >= 0 && num_pages > 0; index--) { |
| 115 | const auto pages_per_alloc{PageHeap::GetBlockNumPages(index)}; | 116 | const auto pages_per_alloc{KPageHeap::GetBlockNumPages(index)}; |
| 116 | 117 | ||
| 117 | while (num_pages >= pages_per_alloc) { | 118 | while (num_pages >= pages_per_alloc) { |
| 118 | // Allocate a block | 119 | // Allocate a block |
| 119 | VAddr allocated_block{chosen_manager.AllocateBlock(index)}; | 120 | VAddr allocated_block{chosen_manager.AllocateBlock(index, false)}; |
| 120 | if (!allocated_block) { | 121 | if (!allocated_block) { |
| 121 | break; | 122 | break; |
| 122 | } | 123 | } |
| @@ -148,8 +149,8 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa | |||
| 148 | return RESULT_SUCCESS; | 149 | return RESULT_SUCCESS; |
| 149 | } | 150 | } |
| 150 | 151 | ||
| 151 | ResultCode MemoryManager::Free(PageLinkedList& page_list, std::size_t num_pages, Pool pool, | 152 | ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, |
| 152 | Direction dir) { | 153 | Direction dir) { |
| 153 | // Early return if we're freeing no pages | 154 | // Early return if we're freeing no pages |
| 154 | if (!num_pages) { | 155 | if (!num_pages) { |
| 155 | return RESULT_SUCCESS; | 156 | return RESULT_SUCCESS; |
| @@ -172,4 +173,4 @@ ResultCode MemoryManager::Free(PageLinkedList& page_list, std::size_t num_pages, | |||
| 172 | return RESULT_SUCCESS; | 173 | return RESULT_SUCCESS; |
| 173 | } | 174 | } |
| 174 | 175 | ||
| 175 | } // namespace Kernel::Memory | 176 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/memory/memory_manager.h b/src/core/hle/kernel/k_memory_manager.h index 3cf444857..ae9f683b8 100644 --- a/src/core/hle/kernel/memory/memory_manager.h +++ b/src/core/hle/kernel/k_memory_manager.h | |||
| @@ -6,16 +6,18 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <mutex> | 8 | #include <mutex> |
| 9 | #include <tuple> | ||
| 9 | 10 | ||
| 11 | #include "common/common_funcs.h" | ||
| 10 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 11 | #include "core/hle/kernel/memory/page_heap.h" | 13 | #include "core/hle/kernel/k_page_heap.h" |
| 12 | #include "core/hle/result.h" | 14 | #include "core/hle/result.h" |
| 13 | 15 | ||
| 14 | namespace Kernel::Memory { | 16 | namespace Kernel { |
| 15 | 17 | ||
| 16 | class PageLinkedList; | 18 | class KPageLinkedList; |
| 17 | 19 | ||
| 18 | class MemoryManager final : NonCopyable { | 20 | class KMemoryManager final : NonCopyable { |
| 19 | public: | 21 | public: |
| 20 | enum class Pool : u32 { | 22 | enum class Pool : u32 { |
| 21 | Application = 0, | 23 | Application = 0, |
| @@ -37,29 +39,50 @@ public: | |||
| 37 | Mask = (0xF << Shift), | 39 | Mask = (0xF << Shift), |
| 38 | }; | 40 | }; |
| 39 | 41 | ||
| 40 | MemoryManager() = default; | 42 | KMemoryManager() = default; |
| 41 | 43 | ||
| 42 | constexpr std::size_t GetSize(Pool pool) const { | 44 | constexpr std::size_t GetSize(Pool pool) const { |
| 43 | return managers[static_cast<std::size_t>(pool)].GetSize(); | 45 | return managers[static_cast<std::size_t>(pool)].GetSize(); |
| 44 | } | 46 | } |
| 45 | 47 | ||
| 46 | void InitializeManager(Pool pool, u64 start_address, u64 end_address); | 48 | void InitializeManager(Pool pool, u64 start_address, u64 end_address); |
| 47 | VAddr AllocateContinuous(std::size_t num_pages, std::size_t align_pages, Pool pool, | 49 | |
| 48 | Direction dir = Direction::FromFront); | 50 | VAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option); |
| 49 | ResultCode Allocate(PageLinkedList& page_list, std::size_t num_pages, Pool pool, | 51 | ResultCode Allocate(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, |
| 50 | Direction dir = Direction::FromFront); | 52 | Direction dir = Direction::FromFront); |
| 51 | ResultCode Free(PageLinkedList& page_list, std::size_t num_pages, Pool pool, | 53 | ResultCode Free(KPageLinkedList& page_list, std::size_t num_pages, Pool pool, |
| 52 | Direction dir = Direction::FromFront); | 54 | Direction dir = Direction::FromFront); |
| 53 | 55 | ||
| 54 | static constexpr std::size_t MaxManagerCount = 10; | 56 | static constexpr std::size_t MaxManagerCount = 10; |
| 55 | 57 | ||
| 58 | public: | ||
| 59 | static constexpr u32 EncodeOption(Pool pool, Direction dir) { | ||
| 60 | return (static_cast<u32>(pool) << static_cast<u32>(Pool::Shift)) | | ||
| 61 | (static_cast<u32>(dir) << static_cast<u32>(Direction::Shift)); | ||
| 62 | } | ||
| 63 | |||
| 64 | static constexpr Pool GetPool(u32 option) { | ||
| 65 | return static_cast<Pool>((static_cast<u32>(option) & static_cast<u32>(Pool::Mask)) >> | ||
| 66 | static_cast<u32>(Pool::Shift)); | ||
| 67 | } | ||
| 68 | |||
| 69 | static constexpr Direction GetDirection(u32 option) { | ||
| 70 | return static_cast<Direction>( | ||
| 71 | (static_cast<u32>(option) & static_cast<u32>(Direction::Mask)) >> | ||
| 72 | static_cast<u32>(Direction::Shift)); | ||
| 73 | } | ||
| 74 | |||
| 75 | static constexpr std::tuple<Pool, Direction> DecodeOption(u32 option) { | ||
| 76 | return std::make_tuple(GetPool(option), GetDirection(option)); | ||
| 77 | } | ||
| 78 | |||
| 56 | private: | 79 | private: |
| 57 | class Impl final : NonCopyable { | 80 | class Impl final : NonCopyable { |
| 58 | private: | 81 | private: |
| 59 | using RefCount = u16; | 82 | using RefCount = u16; |
| 60 | 83 | ||
| 61 | private: | 84 | private: |
| 62 | PageHeap heap; | 85 | KPageHeap heap; |
| 63 | Pool pool{}; | 86 | Pool pool{}; |
| 64 | 87 | ||
| 65 | public: | 88 | public: |
| @@ -67,8 +90,8 @@ private: | |||
| 67 | 90 | ||
| 68 | std::size_t Initialize(Pool new_pool, u64 start_address, u64 end_address); | 91 | std::size_t Initialize(Pool new_pool, u64 start_address, u64 end_address); |
| 69 | 92 | ||
| 70 | VAddr AllocateBlock(s32 index) { | 93 | VAddr AllocateBlock(s32 index, bool random) { |
| 71 | return heap.AllocateBlock(index); | 94 | return heap.AllocateBlock(index, random); |
| 72 | } | 95 | } |
| 73 | 96 | ||
| 74 | void Free(VAddr addr, std::size_t num_pages) { | 97 | void Free(VAddr addr, std::size_t num_pages) { |
| @@ -93,4 +116,4 @@ private: | |||
| 93 | std::array<Impl, MaxManagerCount> managers; | 116 | std::array<Impl, MaxManagerCount> managers; |
| 94 | }; | 117 | }; |
| 95 | 118 | ||
| 96 | } // namespace Kernel::Memory | 119 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_page_bitmap.h b/src/core/hle/kernel/k_page_bitmap.h new file mode 100644 index 000000000..c75d667c9 --- /dev/null +++ b/src/core/hle/kernel/k_page_bitmap.h | |||
| @@ -0,0 +1,279 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <bit> | ||
| 9 | |||
| 10 | #include "common/alignment.h" | ||
| 11 | #include "common/assert.h" | ||
| 12 | #include "common/bit_util.h" | ||
| 13 | #include "common/common_types.h" | ||
| 14 | #include "common/tiny_mt.h" | ||
| 15 | #include "core/hle/kernel/k_system_control.h" | ||
| 16 | |||
| 17 | namespace Kernel { | ||
| 18 | |||
| 19 | class KPageBitmap { | ||
| 20 | private: | ||
| 21 | class RandomBitGenerator { | ||
| 22 | private: | ||
| 23 | Common::TinyMT rng{}; | ||
| 24 | u32 entropy{}; | ||
| 25 | u32 bits_available{}; | ||
| 26 | |||
| 27 | private: | ||
| 28 | void RefreshEntropy() { | ||
| 29 | entropy = rng.GenerateRandomU32(); | ||
| 30 | bits_available = static_cast<u32>(Common::BitSize<decltype(entropy)>()); | ||
| 31 | } | ||
| 32 | |||
| 33 | bool GenerateRandomBit() { | ||
| 34 | if (bits_available == 0) { | ||
| 35 | this->RefreshEntropy(); | ||
| 36 | } | ||
| 37 | |||
| 38 | const bool rnd_bit = (entropy & 1) != 0; | ||
| 39 | entropy >>= 1; | ||
| 40 | --bits_available; | ||
| 41 | return rnd_bit; | ||
| 42 | } | ||
| 43 | |||
| 44 | public: | ||
| 45 | RandomBitGenerator() { | ||
| 46 | rng.Initialize(static_cast<u32>(KSystemControl::GenerateRandomU64())); | ||
| 47 | } | ||
| 48 | |||
| 49 | std::size_t SelectRandomBit(u64 bitmap) { | ||
| 50 | u64 selected = 0; | ||
| 51 | |||
| 52 | u64 cur_num_bits = Common::BitSize<decltype(bitmap)>() / 2; | ||
| 53 | u64 cur_mask = (1ULL << cur_num_bits) - 1; | ||
| 54 | |||
| 55 | while (cur_num_bits) { | ||
| 56 | const u64 low = (bitmap >> 0) & cur_mask; | ||
| 57 | const u64 high = (bitmap >> cur_num_bits) & cur_mask; | ||
| 58 | |||
| 59 | bool choose_low; | ||
| 60 | if (high == 0) { | ||
| 61 | // If only low val is set, choose low. | ||
| 62 | choose_low = true; | ||
| 63 | } else if (low == 0) { | ||
| 64 | // If only high val is set, choose high. | ||
| 65 | choose_low = false; | ||
| 66 | } else { | ||
| 67 | // If both are set, choose random. | ||
| 68 | choose_low = this->GenerateRandomBit(); | ||
| 69 | } | ||
| 70 | |||
| 71 | // If we chose low, proceed with low. | ||
| 72 | if (choose_low) { | ||
| 73 | bitmap = low; | ||
| 74 | selected += 0; | ||
| 75 | } else { | ||
| 76 | bitmap = high; | ||
| 77 | selected += cur_num_bits; | ||
| 78 | } | ||
| 79 | |||
| 80 | // Proceed. | ||
| 81 | cur_num_bits /= 2; | ||
| 82 | cur_mask >>= cur_num_bits; | ||
| 83 | } | ||
| 84 | |||
| 85 | return selected; | ||
| 86 | } | ||
| 87 | }; | ||
| 88 | |||
| 89 | public: | ||
| 90 | static constexpr std::size_t MaxDepth = 4; | ||
| 91 | |||
| 92 | private: | ||
| 93 | std::array<u64*, MaxDepth> bit_storages{}; | ||
| 94 | RandomBitGenerator rng{}; | ||
| 95 | std::size_t num_bits{}; | ||
| 96 | std::size_t used_depths{}; | ||
| 97 | |||
| 98 | public: | ||
| 99 | KPageBitmap() = default; | ||
| 100 | |||
| 101 | constexpr std::size_t GetNumBits() const { | ||
| 102 | return num_bits; | ||
| 103 | } | ||
| 104 | constexpr s32 GetHighestDepthIndex() const { | ||
| 105 | return static_cast<s32>(used_depths) - 1; | ||
| 106 | } | ||
| 107 | |||
| 108 | u64* Initialize(u64* storage, std::size_t size) { | ||
| 109 | // Initially, everything is un-set. | ||
| 110 | num_bits = 0; | ||
| 111 | |||
| 112 | // Calculate the needed bitmap depth. | ||
| 113 | used_depths = static_cast<std::size_t>(GetRequiredDepth(size)); | ||
| 114 | ASSERT(used_depths <= MaxDepth); | ||
| 115 | |||
| 116 | // Set the bitmap pointers. | ||
| 117 | for (s32 depth = this->GetHighestDepthIndex(); depth >= 0; depth--) { | ||
| 118 | bit_storages[depth] = storage; | ||
| 119 | size = Common::AlignUp(size, Common::BitSize<u64>()) / Common::BitSize<u64>(); | ||
| 120 | storage += size; | ||
| 121 | } | ||
| 122 | |||
| 123 | return storage; | ||
| 124 | } | ||
| 125 | |||
| 126 | s64 FindFreeBlock(bool random) { | ||
| 127 | uintptr_t offset = 0; | ||
| 128 | s32 depth = 0; | ||
| 129 | |||
| 130 | if (random) { | ||
| 131 | do { | ||
| 132 | const u64 v = bit_storages[depth][offset]; | ||
| 133 | if (v == 0) { | ||
| 134 | // If depth is bigger than zero, then a previous level indicated a block was | ||
| 135 | // free. | ||
| 136 | ASSERT(depth == 0); | ||
| 137 | return -1; | ||
| 138 | } | ||
| 139 | offset = offset * Common::BitSize<u64>() + rng.SelectRandomBit(v); | ||
| 140 | ++depth; | ||
| 141 | } while (depth < static_cast<s32>(used_depths)); | ||
| 142 | } else { | ||
| 143 | do { | ||
| 144 | const u64 v = bit_storages[depth][offset]; | ||
| 145 | if (v == 0) { | ||
| 146 | // If depth is bigger than zero, then a previous level indicated a block was | ||
| 147 | // free. | ||
| 148 | ASSERT(depth == 0); | ||
| 149 | return -1; | ||
| 150 | } | ||
| 151 | offset = offset * Common::BitSize<u64>() + std::countr_zero(v); | ||
| 152 | ++depth; | ||
| 153 | } while (depth < static_cast<s32>(used_depths)); | ||
| 154 | } | ||
| 155 | |||
| 156 | return static_cast<s64>(offset); | ||
| 157 | } | ||
| 158 | |||
| 159 | void SetBit(std::size_t offset) { | ||
| 160 | this->SetBit(this->GetHighestDepthIndex(), offset); | ||
| 161 | num_bits++; | ||
| 162 | } | ||
| 163 | |||
| 164 | void ClearBit(std::size_t offset) { | ||
| 165 | this->ClearBit(this->GetHighestDepthIndex(), offset); | ||
| 166 | num_bits--; | ||
| 167 | } | ||
| 168 | |||
| 169 | bool ClearRange(std::size_t offset, std::size_t count) { | ||
| 170 | s32 depth = this->GetHighestDepthIndex(); | ||
| 171 | u64* bits = bit_storages[depth]; | ||
| 172 | std::size_t bit_ind = offset / Common::BitSize<u64>(); | ||
| 173 | if (count < Common::BitSize<u64>()) { | ||
| 174 | const std::size_t shift = offset % Common::BitSize<u64>(); | ||
| 175 | ASSERT(shift + count <= Common::BitSize<u64>()); | ||
| 176 | // Check that all the bits are set. | ||
| 177 | const u64 mask = ((u64(1) << count) - 1) << shift; | ||
| 178 | u64 v = bits[bit_ind]; | ||
| 179 | if ((v & mask) != mask) { | ||
| 180 | return false; | ||
| 181 | } | ||
| 182 | |||
| 183 | // Clear the bits. | ||
| 184 | v &= ~mask; | ||
| 185 | bits[bit_ind] = v; | ||
| 186 | if (v == 0) { | ||
| 187 | this->ClearBit(depth - 1, bit_ind); | ||
| 188 | } | ||
| 189 | } else { | ||
| 190 | ASSERT(offset % Common::BitSize<u64>() == 0); | ||
| 191 | ASSERT(count % Common::BitSize<u64>() == 0); | ||
| 192 | // Check that all the bits are set. | ||
| 193 | std::size_t remaining = count; | ||
| 194 | std::size_t i = 0; | ||
| 195 | do { | ||
| 196 | if (bits[bit_ind + i++] != ~u64(0)) { | ||
| 197 | return false; | ||
| 198 | } | ||
| 199 | remaining -= Common::BitSize<u64>(); | ||
| 200 | } while (remaining > 0); | ||
| 201 | |||
| 202 | // Clear the bits. | ||
| 203 | remaining = count; | ||
| 204 | i = 0; | ||
| 205 | do { | ||
| 206 | bits[bit_ind + i] = 0; | ||
| 207 | this->ClearBit(depth - 1, bit_ind + i); | ||
| 208 | i++; | ||
| 209 | remaining -= Common::BitSize<u64>(); | ||
| 210 | } while (remaining > 0); | ||
| 211 | } | ||
| 212 | |||
| 213 | num_bits -= count; | ||
| 214 | return true; | ||
| 215 | } | ||
| 216 | |||
| 217 | private: | ||
| 218 | void SetBit(s32 depth, std::size_t offset) { | ||
| 219 | while (depth >= 0) { | ||
| 220 | std::size_t ind = offset / Common::BitSize<u64>(); | ||
| 221 | std::size_t which = offset % Common::BitSize<u64>(); | ||
| 222 | const u64 mask = u64(1) << which; | ||
| 223 | |||
| 224 | u64* bit = std::addressof(bit_storages[depth][ind]); | ||
| 225 | u64 v = *bit; | ||
| 226 | ASSERT((v & mask) == 0); | ||
| 227 | *bit = v | mask; | ||
| 228 | if (v) { | ||
| 229 | break; | ||
| 230 | } | ||
| 231 | offset = ind; | ||
| 232 | depth--; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | void ClearBit(s32 depth, std::size_t offset) { | ||
| 237 | while (depth >= 0) { | ||
| 238 | std::size_t ind = offset / Common::BitSize<u64>(); | ||
| 239 | std::size_t which = offset % Common::BitSize<u64>(); | ||
| 240 | const u64 mask = u64(1) << which; | ||
| 241 | |||
| 242 | u64* bit = std::addressof(bit_storages[depth][ind]); | ||
| 243 | u64 v = *bit; | ||
| 244 | ASSERT((v & mask) != 0); | ||
| 245 | v &= ~mask; | ||
| 246 | *bit = v; | ||
| 247 | if (v) { | ||
| 248 | break; | ||
| 249 | } | ||
| 250 | offset = ind; | ||
| 251 | depth--; | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | private: | ||
| 256 | static constexpr s32 GetRequiredDepth(std::size_t region_size) { | ||
| 257 | s32 depth = 0; | ||
| 258 | while (true) { | ||
| 259 | region_size /= Common::BitSize<u64>(); | ||
| 260 | depth++; | ||
| 261 | if (region_size == 0) { | ||
| 262 | return depth; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | public: | ||
| 268 | static constexpr std::size_t CalculateManagementOverheadSize(std::size_t region_size) { | ||
| 269 | std::size_t overhead_bits = 0; | ||
| 270 | for (s32 depth = GetRequiredDepth(region_size) - 1; depth >= 0; depth--) { | ||
| 271 | region_size = | ||
| 272 | Common::AlignUp(region_size, Common::BitSize<u64>()) / Common::BitSize<u64>(); | ||
| 273 | overhead_bits += region_size; | ||
| 274 | } | ||
| 275 | return overhead_bits * sizeof(u64); | ||
| 276 | } | ||
| 277 | }; | ||
| 278 | |||
| 279 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/memory/page_heap.cpp b/src/core/hle/kernel/k_page_heap.cpp index 0ab1f7205..07e062922 100644 --- a/src/core/hle/kernel/memory/page_heap.cpp +++ b/src/core/hle/kernel/k_page_heap.cpp | |||
| @@ -2,16 +2,13 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #include "core/core.h" | 5 | #include "core/core.h" |
| 9 | #include "core/hle/kernel/memory/page_heap.h" | 6 | #include "core/hle/kernel/k_page_heap.h" |
| 10 | #include "core/memory.h" | 7 | #include "core/memory.h" |
| 11 | 8 | ||
| 12 | namespace Kernel::Memory { | 9 | namespace Kernel { |
| 13 | 10 | ||
| 14 | void PageHeap::Initialize(VAddr address, std::size_t size, std::size_t metadata_size) { | 11 | void KPageHeap::Initialize(VAddr address, std::size_t size, std::size_t metadata_size) { |
| 15 | // Check our assumptions | 12 | // Check our assumptions |
| 16 | ASSERT(Common::IsAligned((address), PageSize)); | 13 | ASSERT(Common::IsAligned((address), PageSize)); |
| 17 | ASSERT(Common::IsAligned(size, PageSize)); | 14 | ASSERT(Common::IsAligned(size, PageSize)); |
| @@ -32,11 +29,11 @@ void PageHeap::Initialize(VAddr address, std::size_t size, std::size_t metadata_ | |||
| 32 | } | 29 | } |
| 33 | } | 30 | } |
| 34 | 31 | ||
| 35 | VAddr PageHeap::AllocateBlock(s32 index) { | 32 | VAddr KPageHeap::AllocateBlock(s32 index, bool random) { |
| 36 | const std::size_t needed_size{blocks[index].GetSize()}; | 33 | const std::size_t needed_size{blocks[index].GetSize()}; |
| 37 | 34 | ||
| 38 | for (s32 i{index}; i < static_cast<s32>(MemoryBlockPageShifts.size()); i++) { | 35 | for (s32 i{index}; i < static_cast<s32>(MemoryBlockPageShifts.size()); i++) { |
| 39 | if (const VAddr addr{blocks[i].PopBlock()}; addr) { | 36 | if (const VAddr addr{blocks[i].PopBlock(random)}; addr) { |
| 40 | if (const std::size_t allocated_size{blocks[i].GetSize()}; | 37 | if (const std::size_t allocated_size{blocks[i].GetSize()}; |
| 41 | allocated_size > needed_size) { | 38 | allocated_size > needed_size) { |
| 42 | Free(addr + needed_size, (allocated_size - needed_size) / PageSize); | 39 | Free(addr + needed_size, (allocated_size - needed_size) / PageSize); |
| @@ -48,13 +45,13 @@ VAddr PageHeap::AllocateBlock(s32 index) { | |||
| 48 | return 0; | 45 | return 0; |
| 49 | } | 46 | } |
| 50 | 47 | ||
| 51 | void PageHeap::FreeBlock(VAddr block, s32 index) { | 48 | void KPageHeap::FreeBlock(VAddr block, s32 index) { |
| 52 | do { | 49 | do { |
| 53 | block = blocks[index++].PushBlock(block); | 50 | block = blocks[index++].PushBlock(block); |
| 54 | } while (block != 0); | 51 | } while (block != 0); |
| 55 | } | 52 | } |
| 56 | 53 | ||
| 57 | void PageHeap::Free(VAddr addr, std::size_t num_pages) { | 54 | void KPageHeap::Free(VAddr addr, std::size_t num_pages) { |
| 58 | // Freeing no pages is a no-op | 55 | // Freeing no pages is a no-op |
| 59 | if (num_pages == 0) { | 56 | if (num_pages == 0) { |
| 60 | return; | 57 | return; |
| @@ -104,16 +101,16 @@ void PageHeap::Free(VAddr addr, std::size_t num_pages) { | |||
| 104 | } | 101 | } |
| 105 | } | 102 | } |
| 106 | 103 | ||
| 107 | std::size_t PageHeap::CalculateMetadataOverheadSize(std::size_t region_size) { | 104 | std::size_t KPageHeap::CalculateManagementOverheadSize(std::size_t region_size) { |
| 108 | std::size_t overhead_size = 0; | 105 | std::size_t overhead_size = 0; |
| 109 | for (std::size_t i = 0; i < MemoryBlockPageShifts.size(); i++) { | 106 | for (std::size_t i = 0; i < MemoryBlockPageShifts.size(); i++) { |
| 110 | const std::size_t cur_block_shift{MemoryBlockPageShifts[i]}; | 107 | const std::size_t cur_block_shift{MemoryBlockPageShifts[i]}; |
| 111 | const std::size_t next_block_shift{ | 108 | const std::size_t next_block_shift{ |
| 112 | (i != MemoryBlockPageShifts.size() - 1) ? MemoryBlockPageShifts[i + 1] : 0}; | 109 | (i != MemoryBlockPageShifts.size() - 1) ? MemoryBlockPageShifts[i + 1] : 0}; |
| 113 | overhead_size += PageHeap::Block::CalculateMetadataOverheadSize( | 110 | overhead_size += KPageHeap::Block::CalculateManagementOverheadSize( |
| 114 | region_size, cur_block_shift, next_block_shift); | 111 | region_size, cur_block_shift, next_block_shift); |
| 115 | } | 112 | } |
| 116 | return Common::AlignUp(overhead_size, PageSize); | 113 | return Common::AlignUp(overhead_size, PageSize); |
| 117 | } | 114 | } |
| 118 | 115 | ||
| 119 | } // namespace Kernel::Memory | 116 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_page_heap.h b/src/core/hle/kernel/k_page_heap.h new file mode 100644 index 000000000..de5d6a189 --- /dev/null +++ b/src/core/hle/kernel/k_page_heap.h | |||
| @@ -0,0 +1,193 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <bit> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "common/alignment.h" | ||
| 12 | #include "common/assert.h" | ||
| 13 | #include "common/common_funcs.h" | ||
| 14 | #include "common/common_types.h" | ||
| 15 | #include "core/hle/kernel/k_page_bitmap.h" | ||
| 16 | #include "core/hle/kernel/memory_types.h" | ||
| 17 | |||
| 18 | namespace Kernel { | ||
| 19 | |||
| 20 | class KPageHeap final : NonCopyable { | ||
| 21 | public: | ||
| 22 | static constexpr s32 GetAlignedBlockIndex(std::size_t num_pages, std::size_t align_pages) { | ||
| 23 | const auto target_pages{std::max(num_pages, align_pages)}; | ||
| 24 | for (std::size_t i = 0; i < NumMemoryBlockPageShifts; i++) { | ||
| 25 | if (target_pages <= | ||
| 26 | (static_cast<std::size_t>(1) << MemoryBlockPageShifts[i]) / PageSize) { | ||
| 27 | return static_cast<s32>(i); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | return -1; | ||
| 31 | } | ||
| 32 | |||
| 33 | static constexpr s32 GetBlockIndex(std::size_t num_pages) { | ||
| 34 | for (s32 i{static_cast<s32>(NumMemoryBlockPageShifts) - 1}; i >= 0; i--) { | ||
| 35 | if (num_pages >= (static_cast<std::size_t>(1) << MemoryBlockPageShifts[i]) / PageSize) { | ||
| 36 | return i; | ||
| 37 | } | ||
| 38 | } | ||
| 39 | return -1; | ||
| 40 | } | ||
| 41 | |||
| 42 | static constexpr std::size_t GetBlockSize(std::size_t index) { | ||
| 43 | return static_cast<std::size_t>(1) << MemoryBlockPageShifts[index]; | ||
| 44 | } | ||
| 45 | |||
| 46 | static constexpr std::size_t GetBlockNumPages(std::size_t index) { | ||
| 47 | return GetBlockSize(index) / PageSize; | ||
| 48 | } | ||
| 49 | |||
| 50 | private: | ||
| 51 | static constexpr std::size_t NumMemoryBlockPageShifts{7}; | ||
| 52 | static constexpr std::array<std::size_t, NumMemoryBlockPageShifts> MemoryBlockPageShifts{ | ||
| 53 | 0xC, 0x10, 0x15, 0x16, 0x19, 0x1D, 0x1E, | ||
| 54 | }; | ||
| 55 | |||
| 56 | class Block final : NonCopyable { | ||
| 57 | private: | ||
| 58 | KPageBitmap bitmap; | ||
| 59 | VAddr heap_address{}; | ||
| 60 | uintptr_t end_offset{}; | ||
| 61 | std::size_t block_shift{}; | ||
| 62 | std::size_t next_block_shift{}; | ||
| 63 | |||
| 64 | public: | ||
| 65 | Block() = default; | ||
| 66 | |||
| 67 | constexpr std::size_t GetShift() const { | ||
| 68 | return block_shift; | ||
| 69 | } | ||
| 70 | constexpr std::size_t GetNextShift() const { | ||
| 71 | return next_block_shift; | ||
| 72 | } | ||
| 73 | constexpr std::size_t GetSize() const { | ||
| 74 | return static_cast<std::size_t>(1) << GetShift(); | ||
| 75 | } | ||
| 76 | constexpr std::size_t GetNumPages() const { | ||
| 77 | return GetSize() / PageSize; | ||
| 78 | } | ||
| 79 | constexpr std::size_t GetNumFreeBlocks() const { | ||
| 80 | return bitmap.GetNumBits(); | ||
| 81 | } | ||
| 82 | constexpr std::size_t GetNumFreePages() const { | ||
| 83 | return GetNumFreeBlocks() * GetNumPages(); | ||
| 84 | } | ||
| 85 | |||
| 86 | u64* Initialize(VAddr addr, std::size_t size, std::size_t bs, std::size_t nbs, | ||
| 87 | u64* bit_storage) { | ||
| 88 | // Set shifts | ||
| 89 | block_shift = bs; | ||
| 90 | next_block_shift = nbs; | ||
| 91 | |||
| 92 | // Align up the address | ||
| 93 | VAddr end{addr + size}; | ||
| 94 | const auto align{(next_block_shift != 0) ? (1ULL << next_block_shift) | ||
| 95 | : (1ULL << block_shift)}; | ||
| 96 | addr = Common::AlignDown((addr), align); | ||
| 97 | end = Common::AlignUp((end), align); | ||
| 98 | |||
| 99 | heap_address = addr; | ||
| 100 | end_offset = (end - addr) / (1ULL << block_shift); | ||
| 101 | return bitmap.Initialize(bit_storage, end_offset); | ||
| 102 | } | ||
| 103 | |||
| 104 | VAddr PushBlock(VAddr address) { | ||
| 105 | // Set the bit for the free block | ||
| 106 | std::size_t offset{(address - heap_address) >> GetShift()}; | ||
| 107 | bitmap.SetBit(offset); | ||
| 108 | |||
| 109 | // If we have a next shift, try to clear the blocks below and return the address | ||
| 110 | if (GetNextShift()) { | ||
| 111 | const auto diff{1ULL << (GetNextShift() - GetShift())}; | ||
| 112 | offset = Common::AlignDown(offset, diff); | ||
| 113 | if (bitmap.ClearRange(offset, diff)) { | ||
| 114 | return heap_address + (offset << GetShift()); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | // We couldn't coalesce, or we're already as big as possible | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | VAddr PopBlock(bool random) { | ||
| 123 | // Find a free block | ||
| 124 | const s64 soffset{bitmap.FindFreeBlock(random)}; | ||
| 125 | if (soffset < 0) { | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | const auto offset{static_cast<std::size_t>(soffset)}; | ||
| 129 | |||
| 130 | // Update our tracking and return it | ||
| 131 | bitmap.ClearBit(offset); | ||
| 132 | return heap_address + (offset << GetShift()); | ||
| 133 | } | ||
| 134 | |||
| 135 | public: | ||
| 136 | static constexpr std::size_t CalculateManagementOverheadSize(std::size_t region_size, | ||
| 137 | std::size_t cur_block_shift, | ||
| 138 | std::size_t next_block_shift) { | ||
| 139 | const auto cur_block_size{(1ULL << cur_block_shift)}; | ||
| 140 | const auto next_block_size{(1ULL << next_block_shift)}; | ||
| 141 | const auto align{(next_block_shift != 0) ? next_block_size : cur_block_size}; | ||
| 142 | return KPageBitmap::CalculateManagementOverheadSize( | ||
| 143 | (align * 2 + Common::AlignUp(region_size, align)) / cur_block_size); | ||
| 144 | } | ||
| 145 | }; | ||
| 146 | |||
| 147 | public: | ||
| 148 | KPageHeap() = default; | ||
| 149 | |||
| 150 | constexpr VAddr GetAddress() const { | ||
| 151 | return heap_address; | ||
| 152 | } | ||
| 153 | constexpr std::size_t GetSize() const { | ||
| 154 | return heap_size; | ||
| 155 | } | ||
| 156 | constexpr VAddr GetEndAddress() const { | ||
| 157 | return GetAddress() + GetSize(); | ||
| 158 | } | ||
| 159 | constexpr std::size_t GetPageOffset(VAddr block) const { | ||
| 160 | return (block - GetAddress()) / PageSize; | ||
| 161 | } | ||
| 162 | |||
| 163 | void Initialize(VAddr heap_address, std::size_t heap_size, std::size_t metadata_size); | ||
| 164 | VAddr AllocateBlock(s32 index, bool random); | ||
| 165 | void Free(VAddr addr, std::size_t num_pages); | ||
| 166 | |||
| 167 | void UpdateUsedSize() { | ||
| 168 | used_size = heap_size - (GetNumFreePages() * PageSize); | ||
| 169 | } | ||
| 170 | |||
| 171 | static std::size_t CalculateManagementOverheadSize(std::size_t region_size); | ||
| 172 | |||
| 173 | private: | ||
| 174 | constexpr std::size_t GetNumFreePages() const { | ||
| 175 | std::size_t num_free{}; | ||
| 176 | |||
| 177 | for (const auto& block : blocks) { | ||
| 178 | num_free += block.GetNumFreePages(); | ||
| 179 | } | ||
| 180 | |||
| 181 | return num_free; | ||
| 182 | } | ||
| 183 | |||
| 184 | void FreeBlock(VAddr block, s32 index); | ||
| 185 | |||
| 186 | VAddr heap_address{}; | ||
| 187 | std::size_t heap_size{}; | ||
| 188 | std::size_t used_size{}; | ||
| 189 | std::array<Block, NumMemoryBlockPageShifts> blocks{}; | ||
| 190 | std::vector<u64> metadata; | ||
| 191 | }; | ||
| 192 | |||
| 193 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/memory/page_linked_list.h b/src/core/hle/kernel/k_page_linked_list.h index 45dc13eaf..64024d01f 100644 --- a/src/core/hle/kernel/memory/page_linked_list.h +++ b/src/core/hle/kernel/k_page_linked_list.h | |||
| @@ -8,12 +8,12 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/hle/kernel/memory/memory_types.h" | 11 | #include "core/hle/kernel/memory_types.h" |
| 12 | #include "core/hle/result.h" | 12 | #include "core/hle/result.h" |
| 13 | 13 | ||
| 14 | namespace Kernel::Memory { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | class PageLinkedList final { | 16 | class KPageLinkedList final { |
| 17 | public: | 17 | public: |
| 18 | class Node final { | 18 | class Node final { |
| 19 | public: | 19 | public: |
| @@ -33,8 +33,8 @@ public: | |||
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | public: | 35 | public: |
| 36 | PageLinkedList() = default; | 36 | KPageLinkedList() = default; |
| 37 | PageLinkedList(u64 address, u64 num_pages) { | 37 | KPageLinkedList(u64 address, u64 num_pages) { |
| 38 | ASSERT(AddBlock(address, num_pages).IsSuccess()); | 38 | ASSERT(AddBlock(address, num_pages).IsSuccess()); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| @@ -54,7 +54,7 @@ public: | |||
| 54 | return num_pages; | 54 | return num_pages; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | bool IsEqual(PageLinkedList& other) const { | 57 | bool IsEqual(KPageLinkedList& other) const { |
| 58 | auto this_node = nodes.begin(); | 58 | auto this_node = nodes.begin(); |
| 59 | auto other_node = other.nodes.begin(); | 59 | auto other_node = other.nodes.begin(); |
| 60 | while (this_node != nodes.end() && other_node != other.nodes.end()) { | 60 | while (this_node != nodes.end() && other_node != other.nodes.end()) { |
| @@ -89,4 +89,4 @@ private: | |||
| 89 | std::list<Node> nodes; | 89 | std::list<Node> nodes; |
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | } // namespace Kernel::Memory | 92 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 00ed9b881..d09d5ce48 100644 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -6,19 +6,20 @@ | |||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/scope_exit.h" | 7 | #include "common/scope_exit.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/hle/kernel/k_address_space_info.h" | ||
| 10 | #include "core/hle/kernel/k_memory_block.h" | ||
| 11 | #include "core/hle/kernel/k_memory_block_manager.h" | ||
| 12 | #include "core/hle/kernel/k_page_linked_list.h" | ||
| 13 | #include "core/hle/kernel/k_page_table.h" | ||
| 14 | #include "core/hle/kernel/k_resource_limit.h" | ||
| 9 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | 15 | #include "core/hle/kernel/k_scoped_resource_reservation.h" |
| 16 | #include "core/hle/kernel/k_system_control.h" | ||
| 10 | #include "core/hle/kernel/kernel.h" | 17 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/memory/address_space_info.h" | ||
| 12 | #include "core/hle/kernel/memory/memory_block.h" | ||
| 13 | #include "core/hle/kernel/memory/memory_block_manager.h" | ||
| 14 | #include "core/hle/kernel/memory/page_linked_list.h" | ||
| 15 | #include "core/hle/kernel/memory/page_table.h" | ||
| 16 | #include "core/hle/kernel/memory/system_control.h" | ||
| 17 | #include "core/hle/kernel/process.h" | 18 | #include "core/hle/kernel/process.h" |
| 18 | #include "core/hle/kernel/svc_results.h" | 19 | #include "core/hle/kernel/svc_results.h" |
| 19 | #include "core/memory.h" | 20 | #include "core/memory.h" |
| 20 | 21 | ||
| 21 | namespace Kernel::Memory { | 22 | namespace Kernel { |
| 22 | 23 | ||
| 23 | namespace { | 24 | namespace { |
| 24 | 25 | ||
| @@ -37,14 +38,14 @@ constexpr std::size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceT | |||
| 37 | } | 38 | } |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | constexpr u64 GetAddressInRange(const MemoryInfo& info, VAddr addr) { | 41 | constexpr u64 GetAddressInRange(const KMemoryInfo& info, VAddr addr) { |
| 41 | if (info.GetAddress() < addr) { | 42 | if (info.GetAddress() < addr) { |
| 42 | return addr; | 43 | return addr; |
| 43 | } | 44 | } |
| 44 | return info.GetAddress(); | 45 | return info.GetAddress(); |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 47 | constexpr std::size_t GetSizeInRange(const MemoryInfo& info, VAddr start, VAddr end) { | 48 | constexpr std::size_t GetSizeInRange(const KMemoryInfo& info, VAddr start, VAddr end) { |
| 48 | std::size_t size{info.GetSize()}; | 49 | std::size_t size{info.GetSize()}; |
| 49 | if (info.GetAddress() < start) { | 50 | if (info.GetAddress() < start) { |
| 50 | size -= start - info.GetAddress(); | 51 | size -= start - info.GetAddress(); |
| @@ -57,25 +58,25 @@ constexpr std::size_t GetSizeInRange(const MemoryInfo& info, VAddr start, VAddr | |||
| 57 | 58 | ||
| 58 | } // namespace | 59 | } // namespace |
| 59 | 60 | ||
| 60 | PageTable::PageTable(Core::System& system) : system{system} {} | 61 | KPageTable::KPageTable(Core::System& system) : system{system} {} |
| 61 | 62 | ||
| 62 | ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, | 63 | ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, |
| 63 | bool enable_aslr, VAddr code_addr, std::size_t code_size, | 64 | bool enable_aslr, VAddr code_addr, |
| 64 | Memory::MemoryManager::Pool pool) { | 65 | std::size_t code_size, KMemoryManager::Pool pool) { |
| 65 | 66 | ||
| 66 | const auto GetSpaceStart = [this](AddressSpaceInfo::Type type) { | 67 | const auto GetSpaceStart = [this](KAddressSpaceInfo::Type type) { |
| 67 | return AddressSpaceInfo::GetAddressSpaceStart(address_space_width, type); | 68 | return KAddressSpaceInfo::GetAddressSpaceStart(address_space_width, type); |
| 68 | }; | 69 | }; |
| 69 | const auto GetSpaceSize = [this](AddressSpaceInfo::Type type) { | 70 | const auto GetSpaceSize = [this](KAddressSpaceInfo::Type type) { |
| 70 | return AddressSpaceInfo::GetAddressSpaceSize(address_space_width, type); | 71 | return KAddressSpaceInfo::GetAddressSpaceSize(address_space_width, type); |
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| 73 | // Set our width and heap/alias sizes | 74 | // Set our width and heap/alias sizes |
| 74 | address_space_width = GetAddressSpaceWidthFromType(as_type); | 75 | address_space_width = GetAddressSpaceWidthFromType(as_type); |
| 75 | const VAddr start = 0; | 76 | const VAddr start = 0; |
| 76 | const VAddr end{1ULL << address_space_width}; | 77 | const VAddr end{1ULL << address_space_width}; |
| 77 | std::size_t alias_region_size{GetSpaceSize(AddressSpaceInfo::Type::Alias)}; | 78 | std::size_t alias_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Alias)}; |
| 78 | std::size_t heap_region_size{GetSpaceSize(AddressSpaceInfo::Type::Heap)}; | 79 | std::size_t heap_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Heap)}; |
| 79 | 80 | ||
| 80 | ASSERT(start <= code_addr); | 81 | ASSERT(start <= code_addr); |
| 81 | ASSERT(code_addr < code_addr + code_size); | 82 | ASSERT(code_addr < code_addr + code_size); |
| @@ -95,12 +96,12 @@ ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_t | |||
| 95 | std::size_t kernel_map_region_size{}; | 96 | std::size_t kernel_map_region_size{}; |
| 96 | 97 | ||
| 97 | if (address_space_width == 39) { | 98 | if (address_space_width == 39) { |
| 98 | alias_region_size = GetSpaceSize(AddressSpaceInfo::Type::Alias); | 99 | alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type::Alias); |
| 99 | heap_region_size = GetSpaceSize(AddressSpaceInfo::Type::Heap); | 100 | heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type::Heap); |
| 100 | stack_region_size = GetSpaceSize(AddressSpaceInfo::Type::Stack); | 101 | stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type::Stack); |
| 101 | kernel_map_region_size = GetSpaceSize(AddressSpaceInfo::Type::Is32Bit); | 102 | kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type::MapSmall); |
| 102 | code_region_start = GetSpaceStart(AddressSpaceInfo::Type::Large64Bit); | 103 | code_region_start = GetSpaceStart(KAddressSpaceInfo::Type::Map39Bit); |
| 103 | code_region_end = code_region_start + GetSpaceSize(AddressSpaceInfo::Type::Large64Bit); | 104 | code_region_end = code_region_start + GetSpaceSize(KAddressSpaceInfo::Type::Map39Bit); |
| 104 | alias_code_region_start = code_region_start; | 105 | alias_code_region_start = code_region_start; |
| 105 | alias_code_region_end = code_region_end; | 106 | alias_code_region_end = code_region_end; |
| 106 | process_code_start = Common::AlignDown(code_addr, RegionAlignment); | 107 | process_code_start = Common::AlignDown(code_addr, RegionAlignment); |
| @@ -108,12 +109,12 @@ ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_t | |||
| 108 | } else { | 109 | } else { |
| 109 | stack_region_size = 0; | 110 | stack_region_size = 0; |
| 110 | kernel_map_region_size = 0; | 111 | kernel_map_region_size = 0; |
| 111 | code_region_start = GetSpaceStart(AddressSpaceInfo::Type::Is32Bit); | 112 | code_region_start = GetSpaceStart(KAddressSpaceInfo::Type::MapSmall); |
| 112 | code_region_end = code_region_start + GetSpaceSize(AddressSpaceInfo::Type::Is32Bit); | 113 | code_region_end = code_region_start + GetSpaceSize(KAddressSpaceInfo::Type::MapSmall); |
| 113 | stack_region_start = code_region_start; | 114 | stack_region_start = code_region_start; |
| 114 | alias_code_region_start = code_region_start; | 115 | alias_code_region_start = code_region_start; |
| 115 | alias_code_region_end = GetSpaceStart(AddressSpaceInfo::Type::Small64Bit) + | 116 | alias_code_region_end = GetSpaceStart(KAddressSpaceInfo::Type::MapLarge) + |
| 116 | GetSpaceSize(AddressSpaceInfo::Type::Small64Bit); | 117 | GetSpaceSize(KAddressSpaceInfo::Type::MapLarge); |
| 117 | stack_region_end = code_region_end; | 118 | stack_region_end = code_region_end; |
| 118 | kernel_map_region_start = code_region_start; | 119 | kernel_map_region_start = code_region_start; |
| 119 | kernel_map_region_end = code_region_end; | 120 | kernel_map_region_end = code_region_end; |
| @@ -149,13 +150,13 @@ ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_t | |||
| 149 | // Determine random placements for each region | 150 | // Determine random placements for each region |
| 150 | std::size_t alias_rnd{}, heap_rnd{}, stack_rnd{}, kmap_rnd{}; | 151 | std::size_t alias_rnd{}, heap_rnd{}, stack_rnd{}, kmap_rnd{}; |
| 151 | if (enable_aslr) { | 152 | if (enable_aslr) { |
| 152 | alias_rnd = SystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * | 153 | alias_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * |
| 153 | RegionAlignment; | 154 | RegionAlignment; |
| 154 | heap_rnd = SystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * | 155 | heap_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * |
| 155 | RegionAlignment; | 156 | RegionAlignment; |
| 156 | stack_rnd = SystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * | 157 | stack_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * |
| 157 | RegionAlignment; | 158 | RegionAlignment; |
| 158 | kmap_rnd = SystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * | 159 | kmap_rnd = KSystemControl::GenerateRandomRange(0, remaining_size / RegionAlignment) * |
| 159 | RegionAlignment; | 160 | RegionAlignment; |
| 160 | } | 161 | } |
| 161 | 162 | ||
| @@ -270,8 +271,8 @@ ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_t | |||
| 270 | return InitializeMemoryLayout(start, end); | 271 | return InitializeMemoryLayout(start, end); |
| 271 | } | 272 | } |
| 272 | 273 | ||
| 273 | ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemoryState state, | 274 | ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemoryState state, |
| 274 | MemoryPermission perm) { | 275 | KMemoryPermission perm) { |
| 275 | std::lock_guard lock{page_table_lock}; | 276 | std::lock_guard lock{page_table_lock}; |
| 276 | 277 | ||
| 277 | const u64 size{num_pages * PageSize}; | 278 | const u64 size{num_pages * PageSize}; |
| @@ -284,7 +285,7 @@ ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemorySt | |||
| 284 | return ResultInvalidCurrentMemory; | 285 | return ResultInvalidCurrentMemory; |
| 285 | } | 286 | } |
| 286 | 287 | ||
| 287 | PageLinkedList page_linked_list; | 288 | KPageLinkedList page_linked_list; |
| 288 | CASCADE_CODE( | 289 | CASCADE_CODE( |
| 289 | system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool)); | 290 | system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool)); |
| 290 | CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup)); | 291 | CASCADE_CODE(Operate(addr, num_pages, page_linked_list, OperationType::MapGroup)); |
| @@ -294,44 +295,44 @@ ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemorySt | |||
| 294 | return RESULT_SUCCESS; | 295 | return RESULT_SUCCESS; |
| 295 | } | 296 | } |
| 296 | 297 | ||
| 297 | ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { | 298 | ResultCode KPageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { |
| 298 | std::lock_guard lock{page_table_lock}; | 299 | std::lock_guard lock{page_table_lock}; |
| 299 | 300 | ||
| 300 | const std::size_t num_pages{size / PageSize}; | 301 | const std::size_t num_pages{size / PageSize}; |
| 301 | 302 | ||
| 302 | MemoryState state{}; | 303 | KMemoryState state{}; |
| 303 | MemoryPermission perm{}; | 304 | KMemoryPermission perm{}; |
| 304 | CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, MemoryState::All, | 305 | CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, KMemoryState::All, |
| 305 | MemoryState::Normal, MemoryPermission::Mask, | 306 | KMemoryState::Normal, KMemoryPermission::Mask, |
| 306 | MemoryPermission::ReadAndWrite, MemoryAttribute::Mask, | 307 | KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, |
| 307 | MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped)); | 308 | KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); |
| 308 | 309 | ||
| 309 | if (IsRegionMapped(dst_addr, size)) { | 310 | if (IsRegionMapped(dst_addr, size)) { |
| 310 | return ResultInvalidCurrentMemory; | 311 | return ResultInvalidCurrentMemory; |
| 311 | } | 312 | } |
| 312 | 313 | ||
| 313 | PageLinkedList page_linked_list; | 314 | KPageLinkedList page_linked_list; |
| 314 | AddRegionToPages(src_addr, num_pages, page_linked_list); | 315 | AddRegionToPages(src_addr, num_pages, page_linked_list); |
| 315 | 316 | ||
| 316 | { | 317 | { |
| 317 | auto block_guard = detail::ScopeExit( | 318 | auto block_guard = detail::ScopeExit( |
| 318 | [&] { Operate(src_addr, num_pages, perm, OperationType::ChangePermissions); }); | 319 | [&] { Operate(src_addr, num_pages, perm, OperationType::ChangePermissions); }); |
| 319 | 320 | ||
| 320 | CASCADE_CODE( | 321 | CASCADE_CODE(Operate(src_addr, num_pages, KMemoryPermission::None, |
| 321 | Operate(src_addr, num_pages, MemoryPermission::None, OperationType::ChangePermissions)); | 322 | OperationType::ChangePermissions)); |
| 322 | CASCADE_CODE(MapPages(dst_addr, page_linked_list, MemoryPermission::None)); | 323 | CASCADE_CODE(MapPages(dst_addr, page_linked_list, KMemoryPermission::None)); |
| 323 | 324 | ||
| 324 | block_guard.Cancel(); | 325 | block_guard.Cancel(); |
| 325 | } | 326 | } |
| 326 | 327 | ||
| 327 | block_manager->Update(src_addr, num_pages, state, MemoryPermission::None, | 328 | block_manager->Update(src_addr, num_pages, state, KMemoryPermission::None, |
| 328 | MemoryAttribute::Locked); | 329 | KMemoryAttribute::Locked); |
| 329 | block_manager->Update(dst_addr, num_pages, MemoryState::AliasCode); | 330 | block_manager->Update(dst_addr, num_pages, KMemoryState::AliasCode); |
| 330 | 331 | ||
| 331 | return RESULT_SUCCESS; | 332 | return RESULT_SUCCESS; |
| 332 | } | 333 | } |
| 333 | 334 | ||
| 334 | ResultCode PageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { | 335 | ResultCode KPageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { |
| 335 | std::lock_guard lock{page_table_lock}; | 336 | std::lock_guard lock{page_table_lock}; |
| 336 | 337 | ||
| 337 | if (!size) { | 338 | if (!size) { |
| @@ -340,34 +341,35 @@ ResultCode PageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std | |||
| 340 | 341 | ||
| 341 | const std::size_t num_pages{size / PageSize}; | 342 | const std::size_t num_pages{size / PageSize}; |
| 342 | 343 | ||
| 343 | CASCADE_CODE(CheckMemoryState(nullptr, nullptr, nullptr, src_addr, size, MemoryState::All, | 344 | CASCADE_CODE(CheckMemoryState(nullptr, nullptr, nullptr, src_addr, size, KMemoryState::All, |
| 344 | MemoryState::Normal, MemoryPermission::None, | 345 | KMemoryState::Normal, KMemoryPermission::None, |
| 345 | MemoryPermission::None, MemoryAttribute::Mask, | 346 | KMemoryPermission::None, KMemoryAttribute::Mask, |
| 346 | MemoryAttribute::Locked, MemoryAttribute::IpcAndDeviceMapped)); | 347 | KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); |
| 347 | 348 | ||
| 348 | MemoryState state{}; | 349 | KMemoryState state{}; |
| 349 | CASCADE_CODE(CheckMemoryState( | 350 | CASCADE_CODE(CheckMemoryState( |
| 350 | &state, nullptr, nullptr, dst_addr, PageSize, MemoryState::FlagCanCodeAlias, | 351 | &state, nullptr, nullptr, dst_addr, PageSize, KMemoryState::FlagCanCodeAlias, |
| 351 | MemoryState::FlagCanCodeAlias, MemoryPermission::None, MemoryPermission::None, | 352 | KMemoryState::FlagCanCodeAlias, KMemoryPermission::None, KMemoryPermission::None, |
| 352 | MemoryAttribute::Mask, MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped)); | 353 | KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); |
| 353 | CASCADE_CODE(CheckMemoryState(dst_addr, size, MemoryState::All, state, MemoryPermission::None, | 354 | CASCADE_CODE(CheckMemoryState(dst_addr, size, KMemoryState::All, state, KMemoryPermission::None, |
| 354 | MemoryPermission::None, MemoryAttribute::Mask, | 355 | KMemoryPermission::None, KMemoryAttribute::Mask, |
| 355 | MemoryAttribute::None)); | 356 | KMemoryAttribute::None)); |
| 356 | CASCADE_CODE(Operate(dst_addr, num_pages, MemoryPermission::None, OperationType::Unmap)); | 357 | CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap)); |
| 357 | 358 | ||
| 358 | block_manager->Update(dst_addr, num_pages, MemoryState::Free); | 359 | block_manager->Update(dst_addr, num_pages, KMemoryState::Free); |
| 359 | block_manager->Update(src_addr, num_pages, MemoryState::Normal, MemoryPermission::ReadAndWrite); | 360 | block_manager->Update(src_addr, num_pages, KMemoryState::Normal, |
| 361 | KMemoryPermission::ReadAndWrite); | ||
| 360 | 362 | ||
| 361 | return RESULT_SUCCESS; | 363 | return RESULT_SUCCESS; |
| 362 | } | 364 | } |
| 363 | 365 | ||
| 364 | void PageTable::MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, VAddr end) { | 366 | void KPageTable::MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end) { |
| 365 | auto node{page_linked_list.Nodes().begin()}; | 367 | auto node{page_linked_list.Nodes().begin()}; |
| 366 | PAddr map_addr{node->GetAddress()}; | 368 | PAddr map_addr{node->GetAddress()}; |
| 367 | std::size_t src_num_pages{node->GetNumPages()}; | 369 | std::size_t src_num_pages{node->GetNumPages()}; |
| 368 | 370 | ||
| 369 | block_manager->IterateForRange(start, end, [&](const MemoryInfo& info) { | 371 | block_manager->IterateForRange(start, end, [&](const KMemoryInfo& info) { |
| 370 | if (info.state != MemoryState::Free) { | 372 | if (info.state != KMemoryState::Free) { |
| 371 | return; | 373 | return; |
| 372 | } | 374 | } |
| 373 | 375 | ||
| @@ -382,7 +384,7 @@ void PageTable::MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, | |||
| 382 | } | 384 | } |
| 383 | 385 | ||
| 384 | const std::size_t num_pages{std::min(src_num_pages, dst_num_pages)}; | 386 | const std::size_t num_pages{std::min(src_num_pages, dst_num_pages)}; |
| 385 | Operate(dst_addr, num_pages, MemoryPermission::ReadAndWrite, OperationType::Map, | 387 | Operate(dst_addr, num_pages, KMemoryPermission::ReadAndWrite, OperationType::Map, |
| 386 | map_addr); | 388 | map_addr); |
| 387 | 389 | ||
| 388 | dst_addr += num_pages * PageSize; | 390 | dst_addr += num_pages * PageSize; |
| @@ -393,14 +395,14 @@ void PageTable::MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, | |||
| 393 | }); | 395 | }); |
| 394 | } | 396 | } |
| 395 | 397 | ||
| 396 | ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { | 398 | ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { |
| 397 | std::lock_guard lock{page_table_lock}; | 399 | std::lock_guard lock{page_table_lock}; |
| 398 | 400 | ||
| 399 | std::size_t mapped_size{}; | 401 | std::size_t mapped_size{}; |
| 400 | const VAddr end_addr{addr + size}; | 402 | const VAddr end_addr{addr + size}; |
| 401 | 403 | ||
| 402 | block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) { | 404 | block_manager->IterateForRange(addr, end_addr, [&](const KMemoryInfo& info) { |
| 403 | if (info.state != MemoryState::Free) { | 405 | if (info.state != KMemoryState::Free) { |
| 404 | mapped_size += GetSizeInRange(info, addr, end_addr); | 406 | mapped_size += GetSizeInRange(info, addr, end_addr); |
| 405 | } | 407 | } |
| 406 | }); | 408 | }); |
| @@ -421,7 +423,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 421 | return ResultResourceLimitedExceeded; | 423 | return ResultResourceLimitedExceeded; |
| 422 | } | 424 | } |
| 423 | 425 | ||
| 424 | PageLinkedList page_linked_list; | 426 | KPageLinkedList page_linked_list; |
| 425 | 427 | ||
| 426 | CASCADE_CODE( | 428 | CASCADE_CODE( |
| 427 | system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, memory_pool)); | 429 | system.Kernel().MemoryManager().Allocate(page_linked_list, remaining_pages, memory_pool)); |
| @@ -434,14 +436,14 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 434 | physical_memory_usage += remaining_size; | 436 | physical_memory_usage += remaining_size; |
| 435 | 437 | ||
| 436 | const std::size_t num_pages{size / PageSize}; | 438 | const std::size_t num_pages{size / PageSize}; |
| 437 | block_manager->Update(addr, num_pages, MemoryState::Free, MemoryPermission::None, | 439 | block_manager->Update(addr, num_pages, KMemoryState::Free, KMemoryPermission::None, |
| 438 | MemoryAttribute::None, MemoryState::Normal, | 440 | KMemoryAttribute::None, KMemoryState::Normal, |
| 439 | MemoryPermission::ReadAndWrite, MemoryAttribute::None); | 441 | KMemoryPermission::ReadAndWrite, KMemoryAttribute::None); |
| 440 | 442 | ||
| 441 | return RESULT_SUCCESS; | 443 | return RESULT_SUCCESS; |
| 442 | } | 444 | } |
| 443 | 445 | ||
| 444 | ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { | 446 | ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { |
| 445 | std::lock_guard lock{page_table_lock}; | 447 | std::lock_guard lock{page_table_lock}; |
| 446 | 448 | ||
| 447 | const VAddr end_addr{addr + size}; | 449 | const VAddr end_addr{addr + size}; |
| @@ -449,14 +451,14 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 449 | std::size_t mapped_size{}; | 451 | std::size_t mapped_size{}; |
| 450 | 452 | ||
| 451 | // Verify that the region can be unmapped | 453 | // Verify that the region can be unmapped |
| 452 | block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) { | 454 | block_manager->IterateForRange(addr, end_addr, [&](const KMemoryInfo& info) { |
| 453 | if (info.state == MemoryState::Normal) { | 455 | if (info.state == KMemoryState::Normal) { |
| 454 | if (info.attribute != MemoryAttribute::None) { | 456 | if (info.attribute != KMemoryAttribute::None) { |
| 455 | result = ResultInvalidCurrentMemory; | 457 | result = ResultInvalidCurrentMemory; |
| 456 | return; | 458 | return; |
| 457 | } | 459 | } |
| 458 | mapped_size += GetSizeInRange(info, addr, end_addr); | 460 | mapped_size += GetSizeInRange(info, addr, end_addr); |
| 459 | } else if (info.state != MemoryState::Free) { | 461 | } else if (info.state != KMemoryState::Free) { |
| 460 | result = ResultInvalidCurrentMemory; | 462 | result = ResultInvalidCurrentMemory; |
| 461 | } | 463 | } |
| 462 | }); | 464 | }); |
| @@ -478,23 +480,23 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { | |||
| 478 | return RESULT_SUCCESS; | 480 | return RESULT_SUCCESS; |
| 479 | } | 481 | } |
| 480 | 482 | ||
| 481 | ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) { | 483 | ResultCode KPageTable::UnmapMemory(VAddr addr, std::size_t size) { |
| 482 | std::lock_guard lock{page_table_lock}; | 484 | std::lock_guard lock{page_table_lock}; |
| 483 | 485 | ||
| 484 | const VAddr end_addr{addr + size}; | 486 | const VAddr end_addr{addr + size}; |
| 485 | ResultCode result{RESULT_SUCCESS}; | 487 | ResultCode result{RESULT_SUCCESS}; |
| 486 | PageLinkedList page_linked_list; | 488 | KPageLinkedList page_linked_list; |
| 487 | 489 | ||
| 488 | // Unmap each region within the range | 490 | // Unmap each region within the range |
| 489 | block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) { | 491 | block_manager->IterateForRange(addr, end_addr, [&](const KMemoryInfo& info) { |
| 490 | if (info.state == MemoryState::Normal) { | 492 | if (info.state == KMemoryState::Normal) { |
| 491 | const std::size_t block_size{GetSizeInRange(info, addr, end_addr)}; | 493 | const std::size_t block_size{GetSizeInRange(info, addr, end_addr)}; |
| 492 | const std::size_t block_num_pages{block_size / PageSize}; | 494 | const std::size_t block_num_pages{block_size / PageSize}; |
| 493 | const VAddr block_addr{GetAddressInRange(info, addr)}; | 495 | const VAddr block_addr{GetAddressInRange(info, addr)}; |
| 494 | 496 | ||
| 495 | AddRegionToPages(block_addr, block_size / PageSize, page_linked_list); | 497 | AddRegionToPages(block_addr, block_size / PageSize, page_linked_list); |
| 496 | 498 | ||
| 497 | if (result = Operate(block_addr, block_num_pages, MemoryPermission::None, | 499 | if (result = Operate(block_addr, block_num_pages, KMemoryPermission::None, |
| 498 | OperationType::Unmap); | 500 | OperationType::Unmap); |
| 499 | result.IsError()) { | 501 | result.IsError()) { |
| 500 | return; | 502 | return; |
| @@ -509,66 +511,67 @@ ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) { | |||
| 509 | const std::size_t num_pages{size / PageSize}; | 511 | const std::size_t num_pages{size / PageSize}; |
| 510 | system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool); | 512 | system.Kernel().MemoryManager().Free(page_linked_list, num_pages, memory_pool); |
| 511 | 513 | ||
| 512 | block_manager->Update(addr, num_pages, MemoryState::Free); | 514 | block_manager->Update(addr, num_pages, KMemoryState::Free); |
| 513 | 515 | ||
| 514 | return RESULT_SUCCESS; | 516 | return RESULT_SUCCESS; |
| 515 | } | 517 | } |
| 516 | 518 | ||
| 517 | ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) { | 519 | ResultCode KPageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) { |
| 518 | std::lock_guard lock{page_table_lock}; | 520 | std::lock_guard lock{page_table_lock}; |
| 519 | 521 | ||
| 520 | MemoryState src_state{}; | 522 | KMemoryState src_state{}; |
| 521 | CASCADE_CODE(CheckMemoryState( | 523 | CASCADE_CODE(CheckMemoryState( |
| 522 | &src_state, nullptr, nullptr, src_addr, size, MemoryState::FlagCanAlias, | 524 | &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias, |
| 523 | MemoryState::FlagCanAlias, MemoryPermission::Mask, MemoryPermission::ReadAndWrite, | 525 | KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::ReadAndWrite, |
| 524 | MemoryAttribute::Mask, MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped)); | 526 | KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); |
| 525 | 527 | ||
| 526 | if (IsRegionMapped(dst_addr, size)) { | 528 | if (IsRegionMapped(dst_addr, size)) { |
| 527 | return ResultInvalidCurrentMemory; | 529 | return ResultInvalidCurrentMemory; |
| 528 | } | 530 | } |
| 529 | 531 | ||
| 530 | PageLinkedList page_linked_list; | 532 | KPageLinkedList page_linked_list; |
| 531 | const std::size_t num_pages{size / PageSize}; | 533 | const std::size_t num_pages{size / PageSize}; |
| 532 | 534 | ||
| 533 | AddRegionToPages(src_addr, num_pages, page_linked_list); | 535 | AddRegionToPages(src_addr, num_pages, page_linked_list); |
| 534 | 536 | ||
| 535 | { | 537 | { |
| 536 | auto block_guard = detail::ScopeExit([&] { | 538 | auto block_guard = detail::ScopeExit([&] { |
| 537 | Operate(src_addr, num_pages, MemoryPermission::ReadAndWrite, | 539 | Operate(src_addr, num_pages, KMemoryPermission::ReadAndWrite, |
| 538 | OperationType::ChangePermissions); | 540 | OperationType::ChangePermissions); |
| 539 | }); | 541 | }); |
| 540 | 542 | ||
| 541 | CASCADE_CODE( | 543 | CASCADE_CODE(Operate(src_addr, num_pages, KMemoryPermission::None, |
| 542 | Operate(src_addr, num_pages, MemoryPermission::None, OperationType::ChangePermissions)); | 544 | OperationType::ChangePermissions)); |
| 543 | CASCADE_CODE(MapPages(dst_addr, page_linked_list, MemoryPermission::ReadAndWrite)); | 545 | CASCADE_CODE(MapPages(dst_addr, page_linked_list, KMemoryPermission::ReadAndWrite)); |
| 544 | 546 | ||
| 545 | block_guard.Cancel(); | 547 | block_guard.Cancel(); |
| 546 | } | 548 | } |
| 547 | 549 | ||
| 548 | block_manager->Update(src_addr, num_pages, src_state, MemoryPermission::None, | 550 | block_manager->Update(src_addr, num_pages, src_state, KMemoryPermission::None, |
| 549 | MemoryAttribute::Locked); | 551 | KMemoryAttribute::Locked); |
| 550 | block_manager->Update(dst_addr, num_pages, MemoryState::Stack, MemoryPermission::ReadAndWrite); | 552 | block_manager->Update(dst_addr, num_pages, KMemoryState::Stack, |
| 553 | KMemoryPermission::ReadAndWrite); | ||
| 551 | 554 | ||
| 552 | return RESULT_SUCCESS; | 555 | return RESULT_SUCCESS; |
| 553 | } | 556 | } |
| 554 | 557 | ||
| 555 | ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) { | 558 | ResultCode KPageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) { |
| 556 | std::lock_guard lock{page_table_lock}; | 559 | std::lock_guard lock{page_table_lock}; |
| 557 | 560 | ||
| 558 | MemoryState src_state{}; | 561 | KMemoryState src_state{}; |
| 559 | CASCADE_CODE(CheckMemoryState( | 562 | CASCADE_CODE(CheckMemoryState( |
| 560 | &src_state, nullptr, nullptr, src_addr, size, MemoryState::FlagCanAlias, | 563 | &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias, |
| 561 | MemoryState::FlagCanAlias, MemoryPermission::Mask, MemoryPermission::None, | 564 | KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::None, |
| 562 | MemoryAttribute::Mask, MemoryAttribute::Locked, MemoryAttribute::IpcAndDeviceMapped)); | 565 | KMemoryAttribute::Mask, KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); |
| 563 | 566 | ||
| 564 | MemoryPermission dst_perm{}; | 567 | KMemoryPermission dst_perm{}; |
| 565 | CASCADE_CODE(CheckMemoryState(nullptr, &dst_perm, nullptr, dst_addr, size, MemoryState::All, | 568 | CASCADE_CODE(CheckMemoryState(nullptr, &dst_perm, nullptr, dst_addr, size, KMemoryState::All, |
| 566 | MemoryState::Stack, MemoryPermission::None, | 569 | KMemoryState::Stack, KMemoryPermission::None, |
| 567 | MemoryPermission::None, MemoryAttribute::Mask, | 570 | KMemoryPermission::None, KMemoryAttribute::Mask, |
| 568 | MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped)); | 571 | KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); |
| 569 | 572 | ||
| 570 | PageLinkedList src_pages; | 573 | KPageLinkedList src_pages; |
| 571 | PageLinkedList dst_pages; | 574 | KPageLinkedList dst_pages; |
| 572 | const std::size_t num_pages{size / PageSize}; | 575 | const std::size_t num_pages{size / PageSize}; |
| 573 | 576 | ||
| 574 | AddRegionToPages(src_addr, num_pages, src_pages); | 577 | AddRegionToPages(src_addr, num_pages, src_pages); |
| @@ -581,21 +584,21 @@ ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) { | |||
| 581 | { | 584 | { |
| 582 | auto block_guard = detail::ScopeExit([&] { MapPages(dst_addr, dst_pages, dst_perm); }); | 585 | auto block_guard = detail::ScopeExit([&] { MapPages(dst_addr, dst_pages, dst_perm); }); |
| 583 | 586 | ||
| 584 | CASCADE_CODE(Operate(dst_addr, num_pages, MemoryPermission::None, OperationType::Unmap)); | 587 | CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap)); |
| 585 | CASCADE_CODE(Operate(src_addr, num_pages, MemoryPermission::ReadAndWrite, | 588 | CASCADE_CODE(Operate(src_addr, num_pages, KMemoryPermission::ReadAndWrite, |
| 586 | OperationType::ChangePermissions)); | 589 | OperationType::ChangePermissions)); |
| 587 | 590 | ||
| 588 | block_guard.Cancel(); | 591 | block_guard.Cancel(); |
| 589 | } | 592 | } |
| 590 | 593 | ||
| 591 | block_manager->Update(src_addr, num_pages, src_state, MemoryPermission::ReadAndWrite); | 594 | block_manager->Update(src_addr, num_pages, src_state, KMemoryPermission::ReadAndWrite); |
| 592 | block_manager->Update(dst_addr, num_pages, MemoryState::Free); | 595 | block_manager->Update(dst_addr, num_pages, KMemoryState::Free); |
| 593 | 596 | ||
| 594 | return RESULT_SUCCESS; | 597 | return RESULT_SUCCESS; |
| 595 | } | 598 | } |
| 596 | 599 | ||
| 597 | ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_list, | 600 | ResultCode KPageTable::MapPages(VAddr addr, const KPageLinkedList& page_linked_list, |
| 598 | MemoryPermission perm) { | 601 | KMemoryPermission perm) { |
| 599 | VAddr cur_addr{addr}; | 602 | VAddr cur_addr{addr}; |
| 600 | 603 | ||
| 601 | for (const auto& node : page_linked_list.Nodes()) { | 604 | for (const auto& node : page_linked_list.Nodes()) { |
| @@ -604,8 +607,8 @@ ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_lis | |||
| 604 | result.IsError()) { | 607 | result.IsError()) { |
| 605 | const std::size_t num_pages{(addr - cur_addr) / PageSize}; | 608 | const std::size_t num_pages{(addr - cur_addr) / PageSize}; |
| 606 | 609 | ||
| 607 | ASSERT( | 610 | ASSERT(Operate(addr, num_pages, KMemoryPermission::None, OperationType::Unmap) |
| 608 | Operate(addr, num_pages, MemoryPermission::None, OperationType::Unmap).IsSuccess()); | 611 | .IsSuccess()); |
| 609 | 612 | ||
| 610 | return result; | 613 | return result; |
| 611 | } | 614 | } |
| @@ -616,8 +619,8 @@ ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_lis | |||
| 616 | return RESULT_SUCCESS; | 619 | return RESULT_SUCCESS; |
| 617 | } | 620 | } |
| 618 | 621 | ||
| 619 | ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state, | 622 | ResultCode KPageTable::MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, |
| 620 | MemoryPermission perm) { | 623 | KMemoryPermission perm) { |
| 621 | std::lock_guard lock{page_table_lock}; | 624 | std::lock_guard lock{page_table_lock}; |
| 622 | 625 | ||
| 623 | const std::size_t num_pages{page_linked_list.GetNumPages()}; | 626 | const std::size_t num_pages{page_linked_list.GetNumPages()}; |
| @@ -638,26 +641,27 @@ ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, Mem | |||
| 638 | return RESULT_SUCCESS; | 641 | return RESULT_SUCCESS; |
| 639 | } | 642 | } |
| 640 | 643 | ||
| 641 | ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm) { | 644 | ResultCode KPageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, |
| 645 | KMemoryPermission perm) { | ||
| 642 | 646 | ||
| 643 | std::lock_guard lock{page_table_lock}; | 647 | std::lock_guard lock{page_table_lock}; |
| 644 | 648 | ||
| 645 | MemoryState prev_state{}; | 649 | KMemoryState prev_state{}; |
| 646 | MemoryPermission prev_perm{}; | 650 | KMemoryPermission prev_perm{}; |
| 647 | 651 | ||
| 648 | CASCADE_CODE(CheckMemoryState( | 652 | CASCADE_CODE(CheckMemoryState( |
| 649 | &prev_state, &prev_perm, nullptr, addr, size, MemoryState::FlagCode, MemoryState::FlagCode, | 653 | &prev_state, &prev_perm, nullptr, addr, size, KMemoryState::FlagCode, |
| 650 | MemoryPermission::None, MemoryPermission::None, MemoryAttribute::Mask, | 654 | KMemoryState::FlagCode, KMemoryPermission::None, KMemoryPermission::None, |
| 651 | MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped)); | 655 | KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); |
| 652 | 656 | ||
| 653 | MemoryState state{prev_state}; | 657 | KMemoryState state{prev_state}; |
| 654 | 658 | ||
| 655 | // Ensure state is mutable if permission allows write | 659 | // Ensure state is mutable if permission allows write |
| 656 | if ((perm & MemoryPermission::Write) != MemoryPermission::None) { | 660 | if ((perm & KMemoryPermission::Write) != KMemoryPermission::None) { |
| 657 | if (prev_state == MemoryState::Code) { | 661 | if (prev_state == KMemoryState::Code) { |
| 658 | state = MemoryState::CodeData; | 662 | state = KMemoryState::CodeData; |
| 659 | } else if (prev_state == MemoryState::AliasCode) { | 663 | } else if (prev_state == KMemoryState::AliasCode) { |
| 660 | state = MemoryState::AliasCodeData; | 664 | state = KMemoryState::AliasCodeData; |
| 661 | } else { | 665 | } else { |
| 662 | UNREACHABLE(); | 666 | UNREACHABLE(); |
| 663 | } | 667 | } |
| @@ -668,13 +672,13 @@ ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, Memo | |||
| 668 | return RESULT_SUCCESS; | 672 | return RESULT_SUCCESS; |
| 669 | } | 673 | } |
| 670 | 674 | ||
| 671 | if ((prev_perm & MemoryPermission::Execute) != (perm & MemoryPermission::Execute)) { | 675 | if ((prev_perm & KMemoryPermission::Execute) != (perm & KMemoryPermission::Execute)) { |
| 672 | // Memory execution state is changing, invalidate CPU cache range | 676 | // Memory execution state is changing, invalidate CPU cache range |
| 673 | system.InvalidateCpuInstructionCacheRange(addr, size); | 677 | system.InvalidateCpuInstructionCacheRange(addr, size); |
| 674 | } | 678 | } |
| 675 | 679 | ||
| 676 | const std::size_t num_pages{size / PageSize}; | 680 | const std::size_t num_pages{size / PageSize}; |
| 677 | const OperationType operation{(perm & MemoryPermission::Execute) != MemoryPermission::None | 681 | const OperationType operation{(perm & KMemoryPermission::Execute) != KMemoryPermission::None |
| 678 | ? OperationType::ChangePermissionsAndRefresh | 682 | ? OperationType::ChangePermissionsAndRefresh |
| 679 | : OperationType::ChangePermissions}; | 683 | : OperationType::ChangePermissions}; |
| 680 | 684 | ||
| @@ -685,69 +689,69 @@ ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, Memo | |||
| 685 | return RESULT_SUCCESS; | 689 | return RESULT_SUCCESS; |
| 686 | } | 690 | } |
| 687 | 691 | ||
| 688 | MemoryInfo PageTable::QueryInfoImpl(VAddr addr) { | 692 | KMemoryInfo KPageTable::QueryInfoImpl(VAddr addr) { |
| 689 | std::lock_guard lock{page_table_lock}; | 693 | std::lock_guard lock{page_table_lock}; |
| 690 | 694 | ||
| 691 | return block_manager->FindBlock(addr).GetMemoryInfo(); | 695 | return block_manager->FindBlock(addr).GetMemoryInfo(); |
| 692 | } | 696 | } |
| 693 | 697 | ||
| 694 | MemoryInfo PageTable::QueryInfo(VAddr addr) { | 698 | KMemoryInfo KPageTable::QueryInfo(VAddr addr) { |
| 695 | if (!Contains(addr, 1)) { | 699 | if (!Contains(addr, 1)) { |
| 696 | return {address_space_end, 0 - address_space_end, MemoryState::Inaccessible, | 700 | return {address_space_end, 0 - address_space_end, KMemoryState::Inaccessible, |
| 697 | MemoryPermission::None, MemoryAttribute::None, MemoryPermission::None}; | 701 | KMemoryPermission::None, KMemoryAttribute::None, KMemoryPermission::None}; |
| 698 | } | 702 | } |
| 699 | 703 | ||
| 700 | return QueryInfoImpl(addr); | 704 | return QueryInfoImpl(addr); |
| 701 | } | 705 | } |
| 702 | 706 | ||
| 703 | ResultCode PageTable::ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm) { | 707 | ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm) { |
| 704 | std::lock_guard lock{page_table_lock}; | 708 | std::lock_guard lock{page_table_lock}; |
| 705 | 709 | ||
| 706 | MemoryState state{}; | 710 | KMemoryState state{}; |
| 707 | MemoryAttribute attribute{}; | 711 | KMemoryAttribute attribute{}; |
| 708 | 712 | ||
| 709 | CASCADE_CODE(CheckMemoryState(&state, nullptr, &attribute, addr, size, | 713 | CASCADE_CODE(CheckMemoryState( |
| 710 | MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted, | 714 | &state, nullptr, &attribute, addr, size, |
| 711 | MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted, | 715 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, |
| 712 | MemoryPermission::Mask, MemoryPermission::ReadAndWrite, | 716 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::Mask, |
| 713 | MemoryAttribute::Mask, MemoryAttribute::None, | 717 | KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, KMemoryAttribute::None, |
| 714 | MemoryAttribute::IpcAndDeviceMapped)); | 718 | KMemoryAttribute::IpcAndDeviceMapped)); |
| 715 | 719 | ||
| 716 | block_manager->Update(addr, size / PageSize, state, perm, attribute | MemoryAttribute::Locked); | 720 | block_manager->Update(addr, size / PageSize, state, perm, attribute | KMemoryAttribute::Locked); |
| 717 | 721 | ||
| 718 | return RESULT_SUCCESS; | 722 | return RESULT_SUCCESS; |
| 719 | } | 723 | } |
| 720 | 724 | ||
| 721 | ResultCode PageTable::ResetTransferMemory(VAddr addr, std::size_t size) { | 725 | ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) { |
| 722 | std::lock_guard lock{page_table_lock}; | 726 | std::lock_guard lock{page_table_lock}; |
| 723 | 727 | ||
| 724 | MemoryState state{}; | 728 | KMemoryState state{}; |
| 725 | 729 | ||
| 726 | CASCADE_CODE(CheckMemoryState(&state, nullptr, nullptr, addr, size, | 730 | CASCADE_CODE( |
| 727 | MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted, | 731 | CheckMemoryState(&state, nullptr, nullptr, addr, size, |
| 728 | MemoryState::FlagCanTransfer | MemoryState::FlagReferenceCounted, | 732 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, |
| 729 | MemoryPermission::None, MemoryPermission::None, | 733 | KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, |
| 730 | MemoryAttribute::Mask, MemoryAttribute::Locked, | 734 | KMemoryPermission::None, KMemoryPermission::None, KMemoryAttribute::Mask, |
| 731 | MemoryAttribute::IpcAndDeviceMapped)); | 735 | KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); |
| 732 | 736 | ||
| 733 | block_manager->Update(addr, size / PageSize, state, MemoryPermission::ReadAndWrite); | 737 | block_manager->Update(addr, size / PageSize, state, KMemoryPermission::ReadAndWrite); |
| 734 | 738 | ||
| 735 | return RESULT_SUCCESS; | 739 | return RESULT_SUCCESS; |
| 736 | } | 740 | } |
| 737 | 741 | ||
| 738 | ResultCode PageTable::SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask, | 742 | ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, |
| 739 | MemoryAttribute value) { | 743 | KMemoryAttribute value) { |
| 740 | std::lock_guard lock{page_table_lock}; | 744 | std::lock_guard lock{page_table_lock}; |
| 741 | 745 | ||
| 742 | MemoryState state{}; | 746 | KMemoryState state{}; |
| 743 | MemoryPermission perm{}; | 747 | KMemoryPermission perm{}; |
| 744 | MemoryAttribute attribute{}; | 748 | KMemoryAttribute attribute{}; |
| 745 | 749 | ||
| 746 | CASCADE_CODE(CheckMemoryState(&state, &perm, &attribute, addr, size, | 750 | CASCADE_CODE(CheckMemoryState( |
| 747 | MemoryState::FlagCanChangeAttribute, | 751 | &state, &perm, &attribute, addr, size, KMemoryState::FlagCanChangeAttribute, |
| 748 | MemoryState::FlagCanChangeAttribute, MemoryPermission::None, | 752 | KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None, |
| 749 | MemoryPermission::None, MemoryAttribute::LockedAndIpcLocked, | 753 | KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None, |
| 750 | MemoryAttribute::None, MemoryAttribute::DeviceSharedAndUncached)); | 754 | KMemoryAttribute::DeviceSharedAndUncached)); |
| 751 | 755 | ||
| 752 | attribute = attribute & ~mask; | 756 | attribute = attribute & ~mask; |
| 753 | attribute = attribute | (mask & value); | 757 | attribute = attribute | (mask & value); |
| @@ -757,13 +761,13 @@ ResultCode PageTable::SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAtt | |||
| 757 | return RESULT_SUCCESS; | 761 | return RESULT_SUCCESS; |
| 758 | } | 762 | } |
| 759 | 763 | ||
| 760 | ResultCode PageTable::SetHeapCapacity(std::size_t new_heap_capacity) { | 764 | ResultCode KPageTable::SetHeapCapacity(std::size_t new_heap_capacity) { |
| 761 | std::lock_guard lock{page_table_lock}; | 765 | std::lock_guard lock{page_table_lock}; |
| 762 | heap_capacity = new_heap_capacity; | 766 | heap_capacity = new_heap_capacity; |
| 763 | return RESULT_SUCCESS; | 767 | return RESULT_SUCCESS; |
| 764 | } | 768 | } |
| 765 | 769 | ||
| 766 | ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) { | 770 | ResultVal<VAddr> KPageTable::SetHeapSize(std::size_t size) { |
| 767 | 771 | ||
| 768 | if (size > heap_region_end - heap_region_start) { | 772 | if (size > heap_region_end - heap_region_start) { |
| 769 | return ResultOutOfMemory; | 773 | return ResultOutOfMemory; |
| @@ -789,7 +793,7 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) { | |||
| 789 | return ResultResourceLimitedExceeded; | 793 | return ResultResourceLimitedExceeded; |
| 790 | } | 794 | } |
| 791 | 795 | ||
| 792 | PageLinkedList page_linked_list; | 796 | KPageLinkedList page_linked_list; |
| 793 | const std::size_t num_pages{delta / PageSize}; | 797 | const std::size_t num_pages{delta / PageSize}; |
| 794 | 798 | ||
| 795 | CASCADE_CODE( | 799 | CASCADE_CODE( |
| @@ -805,8 +809,8 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) { | |||
| 805 | // Succeeded in allocation, commit the resource reservation | 809 | // Succeeded in allocation, commit the resource reservation |
| 806 | memory_reservation.Commit(); | 810 | memory_reservation.Commit(); |
| 807 | 811 | ||
| 808 | block_manager->Update(current_heap_addr, num_pages, MemoryState::Normal, | 812 | block_manager->Update(current_heap_addr, num_pages, KMemoryState::Normal, |
| 809 | MemoryPermission::ReadAndWrite); | 813 | KMemoryPermission::ReadAndWrite); |
| 810 | 814 | ||
| 811 | current_heap_addr = heap_region_start + size; | 815 | current_heap_addr = heap_region_start + size; |
| 812 | } | 816 | } |
| @@ -814,10 +818,10 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) { | |||
| 814 | return MakeResult<VAddr>(heap_region_start); | 818 | return MakeResult<VAddr>(heap_region_start); |
| 815 | } | 819 | } |
| 816 | 820 | ||
| 817 | ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, | 821 | ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, |
| 818 | bool is_map_only, VAddr region_start, | 822 | bool is_map_only, VAddr region_start, |
| 819 | std::size_t region_num_pages, MemoryState state, | 823 | std::size_t region_num_pages, KMemoryState state, |
| 820 | MemoryPermission perm, PAddr map_addr) { | 824 | KMemoryPermission perm, PAddr map_addr) { |
| 821 | std::lock_guard lock{page_table_lock}; | 825 | std::lock_guard lock{page_table_lock}; |
| 822 | 826 | ||
| 823 | if (!CanContain(region_start, region_num_pages * PageSize, state)) { | 827 | if (!CanContain(region_start, region_num_pages * PageSize, state)) { |
| @@ -837,7 +841,7 @@ ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, s | |||
| 837 | if (is_map_only) { | 841 | if (is_map_only) { |
| 838 | CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr)); | 842 | CASCADE_CODE(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr)); |
| 839 | } else { | 843 | } else { |
| 840 | PageLinkedList page_group; | 844 | KPageLinkedList page_group; |
| 841 | CASCADE_CODE( | 845 | CASCADE_CODE( |
| 842 | system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, memory_pool)); | 846 | system.Kernel().MemoryManager().Allocate(page_group, needed_num_pages, memory_pool)); |
| 843 | CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup)); | 847 | CASCADE_CODE(Operate(addr, needed_num_pages, page_group, OperationType::MapGroup)); |
| @@ -848,22 +852,22 @@ ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, s | |||
| 848 | return MakeResult<VAddr>(addr); | 852 | return MakeResult<VAddr>(addr); |
| 849 | } | 853 | } |
| 850 | 854 | ||
| 851 | ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { | 855 | ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { |
| 852 | std::lock_guard lock{page_table_lock}; | 856 | std::lock_guard lock{page_table_lock}; |
| 853 | 857 | ||
| 854 | MemoryPermission perm{}; | 858 | KMemoryPermission perm{}; |
| 855 | if (const ResultCode result{CheckMemoryState( | 859 | if (const ResultCode result{CheckMemoryState( |
| 856 | nullptr, &perm, nullptr, addr, size, MemoryState::FlagCanChangeAttribute, | 860 | nullptr, &perm, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute, |
| 857 | MemoryState::FlagCanChangeAttribute, MemoryPermission::None, MemoryPermission::None, | 861 | KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None, |
| 858 | MemoryAttribute::LockedAndIpcLocked, MemoryAttribute::None, | 862 | KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None, |
| 859 | MemoryAttribute::DeviceSharedAndUncached)}; | 863 | KMemoryAttribute::DeviceSharedAndUncached)}; |
| 860 | result.IsError()) { | 864 | result.IsError()) { |
| 861 | return result; | 865 | return result; |
| 862 | } | 866 | } |
| 863 | 867 | ||
| 864 | block_manager->UpdateLock( | 868 | block_manager->UpdateLock( |
| 865 | addr, size / PageSize, | 869 | addr, size / PageSize, |
| 866 | [](MemoryBlockManager::iterator block, MemoryPermission perm) { | 870 | [](KMemoryBlockManager::iterator block, KMemoryPermission perm) { |
| 867 | block->ShareToDevice(perm); | 871 | block->ShareToDevice(perm); |
| 868 | }, | 872 | }, |
| 869 | perm); | 873 | perm); |
| @@ -871,22 +875,22 @@ ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { | |||
| 871 | return RESULT_SUCCESS; | 875 | return RESULT_SUCCESS; |
| 872 | } | 876 | } |
| 873 | 877 | ||
| 874 | ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) { | 878 | ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) { |
| 875 | std::lock_guard lock{page_table_lock}; | 879 | std::lock_guard lock{page_table_lock}; |
| 876 | 880 | ||
| 877 | MemoryPermission perm{}; | 881 | KMemoryPermission perm{}; |
| 878 | if (const ResultCode result{CheckMemoryState( | 882 | if (const ResultCode result{CheckMemoryState( |
| 879 | nullptr, &perm, nullptr, addr, size, MemoryState::FlagCanChangeAttribute, | 883 | nullptr, &perm, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute, |
| 880 | MemoryState::FlagCanChangeAttribute, MemoryPermission::None, MemoryPermission::None, | 884 | KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None, |
| 881 | MemoryAttribute::LockedAndIpcLocked, MemoryAttribute::None, | 885 | KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None, |
| 882 | MemoryAttribute::DeviceSharedAndUncached)}; | 886 | KMemoryAttribute::DeviceSharedAndUncached)}; |
| 883 | result.IsError()) { | 887 | result.IsError()) { |
| 884 | return result; | 888 | return result; |
| 885 | } | 889 | } |
| 886 | 890 | ||
| 887 | block_manager->UpdateLock( | 891 | block_manager->UpdateLock( |
| 888 | addr, size / PageSize, | 892 | addr, size / PageSize, |
| 889 | [](MemoryBlockManager::iterator block, MemoryPermission perm) { | 893 | [](KMemoryBlockManager::iterator block, KMemoryPermission perm) { |
| 890 | block->UnshareToDevice(perm); | 894 | block->UnshareToDevice(perm); |
| 891 | }, | 895 | }, |
| 892 | perm); | 896 | perm); |
| @@ -894,20 +898,21 @@ ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) | |||
| 894 | return RESULT_SUCCESS; | 898 | return RESULT_SUCCESS; |
| 895 | } | 899 | } |
| 896 | 900 | ||
| 897 | ResultCode PageTable::InitializeMemoryLayout(VAddr start, VAddr end) { | 901 | ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) { |
| 898 | block_manager = std::make_unique<MemoryBlockManager>(start, end); | 902 | block_manager = std::make_unique<KMemoryBlockManager>(start, end); |
| 899 | 903 | ||
| 900 | return RESULT_SUCCESS; | 904 | return RESULT_SUCCESS; |
| 901 | } | 905 | } |
| 902 | 906 | ||
| 903 | bool PageTable::IsRegionMapped(VAddr address, u64 size) { | 907 | bool KPageTable::IsRegionMapped(VAddr address, u64 size) { |
| 904 | return CheckMemoryState(address, size, MemoryState::All, MemoryState::Free, | 908 | return CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free, |
| 905 | MemoryPermission::Mask, MemoryPermission::None, MemoryAttribute::Mask, | 909 | KMemoryPermission::Mask, KMemoryPermission::None, |
| 906 | MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped) | 910 | KMemoryAttribute::Mask, KMemoryAttribute::None, |
| 911 | KMemoryAttribute::IpcAndDeviceMapped) | ||
| 907 | .IsError(); | 912 | .IsError(); |
| 908 | } | 913 | } |
| 909 | 914 | ||
| 910 | bool PageTable::IsRegionContiguous(VAddr addr, u64 size) const { | 915 | bool KPageTable::IsRegionContiguous(VAddr addr, u64 size) const { |
| 911 | auto start_ptr = system.Memory().GetPointer(addr); | 916 | auto start_ptr = system.Memory().GetPointer(addr); |
| 912 | for (u64 offset{}; offset < size; offset += PageSize) { | 917 | for (u64 offset{}; offset < size; offset += PageSize) { |
| 913 | if (start_ptr != system.Memory().GetPointer(addr + offset)) { | 918 | if (start_ptr != system.Memory().GetPointer(addr + offset)) { |
| @@ -918,8 +923,8 @@ bool PageTable::IsRegionContiguous(VAddr addr, u64 size) const { | |||
| 918 | return true; | 923 | return true; |
| 919 | } | 924 | } |
| 920 | 925 | ||
| 921 | void PageTable::AddRegionToPages(VAddr start, std::size_t num_pages, | 926 | void KPageTable::AddRegionToPages(VAddr start, std::size_t num_pages, |
| 922 | PageLinkedList& page_linked_list) { | 927 | KPageLinkedList& page_linked_list) { |
| 923 | VAddr addr{start}; | 928 | VAddr addr{start}; |
| 924 | while (addr < start + (num_pages * PageSize)) { | 929 | while (addr < start + (num_pages * PageSize)) { |
| 925 | const PAddr paddr{GetPhysicalAddr(addr)}; | 930 | const PAddr paddr{GetPhysicalAddr(addr)}; |
| @@ -931,8 +936,8 @@ void PageTable::AddRegionToPages(VAddr start, std::size_t num_pages, | |||
| 931 | } | 936 | } |
| 932 | } | 937 | } |
| 933 | 938 | ||
| 934 | VAddr PageTable::AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, | 939 | VAddr KPageTable::AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, |
| 935 | u64 needed_num_pages, std::size_t align) { | 940 | u64 needed_num_pages, std::size_t align) { |
| 936 | if (is_aslr_enabled) { | 941 | if (is_aslr_enabled) { |
| 937 | UNIMPLEMENTED(); | 942 | UNIMPLEMENTED(); |
| 938 | } | 943 | } |
| @@ -940,8 +945,8 @@ VAddr PageTable::AllocateVirtualMemory(VAddr start, std::size_t region_num_pages | |||
| 940 | IsKernel() ? 1 : 4); | 945 | IsKernel() ? 1 : 4); |
| 941 | } | 946 | } |
| 942 | 947 | ||
| 943 | ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group, | 948 | ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, const KPageLinkedList& page_group, |
| 944 | OperationType operation) { | 949 | OperationType operation) { |
| 945 | std::lock_guard lock{page_table_lock}; | 950 | std::lock_guard lock{page_table_lock}; |
| 946 | 951 | ||
| 947 | ASSERT(Common::IsAligned(addr, PageSize)); | 952 | ASSERT(Common::IsAligned(addr, PageSize)); |
| @@ -965,8 +970,8 @@ ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, const PageLinke | |||
| 965 | return RESULT_SUCCESS; | 970 | return RESULT_SUCCESS; |
| 966 | } | 971 | } |
| 967 | 972 | ||
| 968 | ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm, | 973 | ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm, |
| 969 | OperationType operation, PAddr map_addr) { | 974 | OperationType operation, PAddr map_addr) { |
| 970 | std::lock_guard lock{page_table_lock}; | 975 | std::lock_guard lock{page_table_lock}; |
| 971 | 976 | ||
| 972 | ASSERT(num_pages > 0); | 977 | ASSERT(num_pages > 0); |
| @@ -992,34 +997,34 @@ ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, MemoryPermissio | |||
| 992 | return RESULT_SUCCESS; | 997 | return RESULT_SUCCESS; |
| 993 | } | 998 | } |
| 994 | 999 | ||
| 995 | constexpr VAddr PageTable::GetRegionAddress(MemoryState state) const { | 1000 | constexpr VAddr KPageTable::GetRegionAddress(KMemoryState state) const { |
| 996 | switch (state) { | 1001 | switch (state) { |
| 997 | case MemoryState::Free: | 1002 | case KMemoryState::Free: |
| 998 | case MemoryState::Kernel: | 1003 | case KMemoryState::Kernel: |
| 999 | return address_space_start; | 1004 | return address_space_start; |
| 1000 | case MemoryState::Normal: | 1005 | case KMemoryState::Normal: |
| 1001 | return heap_region_start; | 1006 | return heap_region_start; |
| 1002 | case MemoryState::Ipc: | 1007 | case KMemoryState::Ipc: |
| 1003 | case MemoryState::NonSecureIpc: | 1008 | case KMemoryState::NonSecureIpc: |
| 1004 | case MemoryState::NonDeviceIpc: | 1009 | case KMemoryState::NonDeviceIpc: |
| 1005 | return alias_region_start; | 1010 | return alias_region_start; |
| 1006 | case MemoryState::Stack: | 1011 | case KMemoryState::Stack: |
| 1007 | return stack_region_start; | 1012 | return stack_region_start; |
| 1008 | case MemoryState::Io: | 1013 | case KMemoryState::Io: |
| 1009 | case MemoryState::Static: | 1014 | case KMemoryState::Static: |
| 1010 | case MemoryState::ThreadLocal: | 1015 | case KMemoryState::ThreadLocal: |
| 1011 | return kernel_map_region_start; | 1016 | return kernel_map_region_start; |
| 1012 | case MemoryState::Shared: | 1017 | case KMemoryState::Shared: |
| 1013 | case MemoryState::AliasCode: | 1018 | case KMemoryState::AliasCode: |
| 1014 | case MemoryState::AliasCodeData: | 1019 | case KMemoryState::AliasCodeData: |
| 1015 | case MemoryState::Transferred: | 1020 | case KMemoryState::Transferred: |
| 1016 | case MemoryState::SharedTransferred: | 1021 | case KMemoryState::SharedTransferred: |
| 1017 | case MemoryState::SharedCode: | 1022 | case KMemoryState::SharedCode: |
| 1018 | case MemoryState::GeneratedCode: | 1023 | case KMemoryState::GeneratedCode: |
| 1019 | case MemoryState::CodeOut: | 1024 | case KMemoryState::CodeOut: |
| 1020 | return alias_code_region_start; | 1025 | return alias_code_region_start; |
| 1021 | case MemoryState::Code: | 1026 | case KMemoryState::Code: |
| 1022 | case MemoryState::CodeData: | 1027 | case KMemoryState::CodeData: |
| 1023 | return code_region_start; | 1028 | return code_region_start; |
| 1024 | default: | 1029 | default: |
| 1025 | UNREACHABLE(); | 1030 | UNREACHABLE(); |
| @@ -1027,34 +1032,34 @@ constexpr VAddr PageTable::GetRegionAddress(MemoryState state) const { | |||
| 1027 | } | 1032 | } |
| 1028 | } | 1033 | } |
| 1029 | 1034 | ||
| 1030 | constexpr std::size_t PageTable::GetRegionSize(MemoryState state) const { | 1035 | constexpr std::size_t KPageTable::GetRegionSize(KMemoryState state) const { |
| 1031 | switch (state) { | 1036 | switch (state) { |
| 1032 | case MemoryState::Free: | 1037 | case KMemoryState::Free: |
| 1033 | case MemoryState::Kernel: | 1038 | case KMemoryState::Kernel: |
| 1034 | return address_space_end - address_space_start; | 1039 | return address_space_end - address_space_start; |
| 1035 | case MemoryState::Normal: | 1040 | case KMemoryState::Normal: |
| 1036 | return heap_region_end - heap_region_start; | 1041 | return heap_region_end - heap_region_start; |
| 1037 | case MemoryState::Ipc: | 1042 | case KMemoryState::Ipc: |
| 1038 | case MemoryState::NonSecureIpc: | 1043 | case KMemoryState::NonSecureIpc: |
| 1039 | case MemoryState::NonDeviceIpc: | 1044 | case KMemoryState::NonDeviceIpc: |
| 1040 | return alias_region_end - alias_region_start; | 1045 | return alias_region_end - alias_region_start; |
| 1041 | case MemoryState::Stack: | 1046 | case KMemoryState::Stack: |
| 1042 | return stack_region_end - stack_region_start; | 1047 | return stack_region_end - stack_region_start; |
| 1043 | case MemoryState::Io: | 1048 | case KMemoryState::Io: |
| 1044 | case MemoryState::Static: | 1049 | case KMemoryState::Static: |
| 1045 | case MemoryState::ThreadLocal: | 1050 | case KMemoryState::ThreadLocal: |
| 1046 | return kernel_map_region_end - kernel_map_region_start; | 1051 | return kernel_map_region_end - kernel_map_region_start; |
| 1047 | case MemoryState::Shared: | 1052 | case KMemoryState::Shared: |
| 1048 | case MemoryState::AliasCode: | 1053 | case KMemoryState::AliasCode: |
| 1049 | case MemoryState::AliasCodeData: | 1054 | case KMemoryState::AliasCodeData: |
| 1050 | case MemoryState::Transferred: | 1055 | case KMemoryState::Transferred: |
| 1051 | case MemoryState::SharedTransferred: | 1056 | case KMemoryState::SharedTransferred: |
| 1052 | case MemoryState::SharedCode: | 1057 | case KMemoryState::SharedCode: |
| 1053 | case MemoryState::GeneratedCode: | 1058 | case KMemoryState::GeneratedCode: |
| 1054 | case MemoryState::CodeOut: | 1059 | case KMemoryState::CodeOut: |
| 1055 | return alias_code_region_end - alias_code_region_start; | 1060 | return alias_code_region_end - alias_code_region_start; |
| 1056 | case MemoryState::Code: | 1061 | case KMemoryState::Code: |
| 1057 | case MemoryState::CodeData: | 1062 | case KMemoryState::CodeData: |
| 1058 | return code_region_end - code_region_start; | 1063 | return code_region_end - code_region_start; |
| 1059 | default: | 1064 | default: |
| 1060 | UNREACHABLE(); | 1065 | UNREACHABLE(); |
| @@ -1062,7 +1067,7 @@ constexpr std::size_t PageTable::GetRegionSize(MemoryState state) const { | |||
| 1062 | } | 1067 | } |
| 1063 | } | 1068 | } |
| 1064 | 1069 | ||
| 1065 | constexpr bool PageTable::CanContain(VAddr addr, std::size_t size, MemoryState state) const { | 1070 | constexpr bool KPageTable::CanContain(VAddr addr, std::size_t size, KMemoryState state) const { |
| 1066 | const VAddr end{addr + size}; | 1071 | const VAddr end{addr + size}; |
| 1067 | const VAddr last{end - 1}; | 1072 | const VAddr last{end - 1}; |
| 1068 | const VAddr region_start{GetRegionAddress(state)}; | 1073 | const VAddr region_start{GetRegionAddress(state)}; |
| @@ -1073,30 +1078,30 @@ constexpr bool PageTable::CanContain(VAddr addr, std::size_t size, MemoryState s | |||
| 1073 | const bool is_in_alias{!(end <= alias_region_start || alias_region_end <= addr)}; | 1078 | const bool is_in_alias{!(end <= alias_region_start || alias_region_end <= addr)}; |
| 1074 | 1079 | ||
| 1075 | switch (state) { | 1080 | switch (state) { |
| 1076 | case MemoryState::Free: | 1081 | case KMemoryState::Free: |
| 1077 | case MemoryState::Kernel: | 1082 | case KMemoryState::Kernel: |
| 1078 | return is_in_region; | 1083 | return is_in_region; |
| 1079 | case MemoryState::Io: | 1084 | case KMemoryState::Io: |
| 1080 | case MemoryState::Static: | 1085 | case KMemoryState::Static: |
| 1081 | case MemoryState::Code: | 1086 | case KMemoryState::Code: |
| 1082 | case MemoryState::CodeData: | 1087 | case KMemoryState::CodeData: |
| 1083 | case MemoryState::Shared: | 1088 | case KMemoryState::Shared: |
| 1084 | case MemoryState::AliasCode: | 1089 | case KMemoryState::AliasCode: |
| 1085 | case MemoryState::AliasCodeData: | 1090 | case KMemoryState::AliasCodeData: |
| 1086 | case MemoryState::Stack: | 1091 | case KMemoryState::Stack: |
| 1087 | case MemoryState::ThreadLocal: | 1092 | case KMemoryState::ThreadLocal: |
| 1088 | case MemoryState::Transferred: | 1093 | case KMemoryState::Transferred: |
| 1089 | case MemoryState::SharedTransferred: | 1094 | case KMemoryState::SharedTransferred: |
| 1090 | case MemoryState::SharedCode: | 1095 | case KMemoryState::SharedCode: |
| 1091 | case MemoryState::GeneratedCode: | 1096 | case KMemoryState::GeneratedCode: |
| 1092 | case MemoryState::CodeOut: | 1097 | case KMemoryState::CodeOut: |
| 1093 | return is_in_region && !is_in_heap && !is_in_alias; | 1098 | return is_in_region && !is_in_heap && !is_in_alias; |
| 1094 | case MemoryState::Normal: | 1099 | case KMemoryState::Normal: |
| 1095 | ASSERT(is_in_heap); | 1100 | ASSERT(is_in_heap); |
| 1096 | return is_in_region && !is_in_alias; | 1101 | return is_in_region && !is_in_alias; |
| 1097 | case MemoryState::Ipc: | 1102 | case KMemoryState::Ipc: |
| 1098 | case MemoryState::NonSecureIpc: | 1103 | case KMemoryState::NonSecureIpc: |
| 1099 | case MemoryState::NonDeviceIpc: | 1104 | case KMemoryState::NonDeviceIpc: |
| 1100 | ASSERT(is_in_alias); | 1105 | ASSERT(is_in_alias); |
| 1101 | return is_in_region && !is_in_heap; | 1106 | return is_in_region && !is_in_heap; |
| 1102 | default: | 1107 | default: |
| @@ -1104,10 +1109,11 @@ constexpr bool PageTable::CanContain(VAddr addr, std::size_t size, MemoryState s | |||
| 1104 | } | 1109 | } |
| 1105 | } | 1110 | } |
| 1106 | 1111 | ||
| 1107 | constexpr ResultCode PageTable::CheckMemoryState(const MemoryInfo& info, MemoryState state_mask, | 1112 | constexpr ResultCode KPageTable::CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask, |
| 1108 | MemoryState state, MemoryPermission perm_mask, | 1113 | KMemoryState state, KMemoryPermission perm_mask, |
| 1109 | MemoryPermission perm, MemoryAttribute attr_mask, | 1114 | KMemoryPermission perm, |
| 1110 | MemoryAttribute attr) const { | 1115 | KMemoryAttribute attr_mask, |
| 1116 | KMemoryAttribute attr) const { | ||
| 1111 | // Validate the states match expectation | 1117 | // Validate the states match expectation |
| 1112 | if ((info.state & state_mask) != state) { | 1118 | if ((info.state & state_mask) != state) { |
| 1113 | return ResultInvalidCurrentMemory; | 1119 | return ResultInvalidCurrentMemory; |
| @@ -1122,23 +1128,23 @@ constexpr ResultCode PageTable::CheckMemoryState(const MemoryInfo& info, MemoryS | |||
| 1122 | return RESULT_SUCCESS; | 1128 | return RESULT_SUCCESS; |
| 1123 | } | 1129 | } |
| 1124 | 1130 | ||
| 1125 | ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission* out_perm, | 1131 | ResultCode KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm, |
| 1126 | MemoryAttribute* out_attr, VAddr addr, std::size_t size, | 1132 | KMemoryAttribute* out_attr, VAddr addr, std::size_t size, |
| 1127 | MemoryState state_mask, MemoryState state, | 1133 | KMemoryState state_mask, KMemoryState state, |
| 1128 | MemoryPermission perm_mask, MemoryPermission perm, | 1134 | KMemoryPermission perm_mask, KMemoryPermission perm, |
| 1129 | MemoryAttribute attr_mask, MemoryAttribute attr, | 1135 | KMemoryAttribute attr_mask, KMemoryAttribute attr, |
| 1130 | MemoryAttribute ignore_attr) { | 1136 | KMemoryAttribute ignore_attr) { |
| 1131 | std::lock_guard lock{page_table_lock}; | 1137 | std::lock_guard lock{page_table_lock}; |
| 1132 | 1138 | ||
| 1133 | // Get information about the first block | 1139 | // Get information about the first block |
| 1134 | const VAddr last_addr{addr + size - 1}; | 1140 | const VAddr last_addr{addr + size - 1}; |
| 1135 | MemoryBlockManager::const_iterator it{block_manager->FindIterator(addr)}; | 1141 | KMemoryBlockManager::const_iterator it{block_manager->FindIterator(addr)}; |
| 1136 | MemoryInfo info{it->GetMemoryInfo()}; | 1142 | KMemoryInfo info{it->GetMemoryInfo()}; |
| 1137 | 1143 | ||
| 1138 | // Validate all blocks in the range have correct state | 1144 | // Validate all blocks in the range have correct state |
| 1139 | const MemoryState first_state{info.state}; | 1145 | const KMemoryState first_state{info.state}; |
| 1140 | const MemoryPermission first_perm{info.perm}; | 1146 | const KMemoryPermission first_perm{info.perm}; |
| 1141 | const MemoryAttribute first_attr{info.attribute}; | 1147 | const KMemoryAttribute first_attr{info.attribute}; |
| 1142 | 1148 | ||
| 1143 | while (true) { | 1149 | while (true) { |
| 1144 | // Validate the current block | 1150 | // Validate the current block |
| @@ -1148,8 +1154,8 @@ ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission* | |||
| 1148 | if (!(info.perm == first_perm)) { | 1154 | if (!(info.perm == first_perm)) { |
| 1149 | return ResultInvalidCurrentMemory; | 1155 | return ResultInvalidCurrentMemory; |
| 1150 | } | 1156 | } |
| 1151 | if (!((info.attribute | static_cast<MemoryAttribute>(ignore_attr)) == | 1157 | if (!((info.attribute | static_cast<KMemoryAttribute>(ignore_attr)) == |
| 1152 | (first_attr | static_cast<MemoryAttribute>(ignore_attr)))) { | 1158 | (first_attr | static_cast<KMemoryAttribute>(ignore_attr)))) { |
| 1153 | return ResultInvalidCurrentMemory; | 1159 | return ResultInvalidCurrentMemory; |
| 1154 | } | 1160 | } |
| 1155 | 1161 | ||
| @@ -1175,10 +1181,10 @@ ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission* | |||
| 1175 | *out_perm = first_perm; | 1181 | *out_perm = first_perm; |
| 1176 | } | 1182 | } |
| 1177 | if (out_attr) { | 1183 | if (out_attr) { |
| 1178 | *out_attr = first_attr & static_cast<MemoryAttribute>(~ignore_attr); | 1184 | *out_attr = first_attr & static_cast<KMemoryAttribute>(~ignore_attr); |
| 1179 | } | 1185 | } |
| 1180 | 1186 | ||
| 1181 | return RESULT_SUCCESS; | 1187 | return RESULT_SUCCESS; |
| 1182 | } | 1188 | } |
| 1183 | 1189 | ||
| 1184 | } // namespace Kernel::Memory | 1190 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/memory/page_table.h b/src/core/hle/kernel/k_page_table.h index ce0d38849..49b824379 100644 --- a/src/core/hle/kernel/memory/page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -10,27 +10,27 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/page_table.h" | 11 | #include "common/page_table.h" |
| 12 | #include "core/file_sys/program_metadata.h" | 12 | #include "core/file_sys/program_metadata.h" |
| 13 | #include "core/hle/kernel/memory/memory_block.h" | 13 | #include "core/hle/kernel/k_memory_block.h" |
| 14 | #include "core/hle/kernel/memory/memory_manager.h" | 14 | #include "core/hle/kernel/k_memory_manager.h" |
| 15 | #include "core/hle/result.h" | 15 | #include "core/hle/result.h" |
| 16 | 16 | ||
| 17 | namespace Core { | 17 | namespace Core { |
| 18 | class System; | 18 | class System; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | namespace Kernel::Memory { | 21 | namespace Kernel { |
| 22 | 22 | ||
| 23 | class MemoryBlockManager; | 23 | class KMemoryBlockManager; |
| 24 | 24 | ||
| 25 | class PageTable final : NonCopyable { | 25 | class KPageTable final : NonCopyable { |
| 26 | public: | 26 | public: |
| 27 | explicit PageTable(Core::System& system); | 27 | explicit KPageTable(Core::System& system); |
| 28 | 28 | ||
| 29 | ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, | 29 | ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, |
| 30 | VAddr code_addr, std::size_t code_size, | 30 | VAddr code_addr, std::size_t code_size, |
| 31 | Memory::MemoryManager::Pool pool); | 31 | KMemoryManager::Pool pool); |
| 32 | ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, MemoryState state, | 32 | ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, KMemoryState state, |
| 33 | MemoryPermission perm); | 33 | KMemoryPermission perm); |
| 34 | ResultCode MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); | 34 | ResultCode MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); |
| 35 | ResultCode UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); | 35 | ResultCode UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); |
| 36 | ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); | 36 | ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); |
| @@ -38,20 +38,20 @@ public: | |||
| 38 | ResultCode UnmapMemory(VAddr addr, std::size_t size); | 38 | ResultCode UnmapMemory(VAddr addr, std::size_t size); |
| 39 | ResultCode Map(VAddr dst_addr, VAddr src_addr, std::size_t size); | 39 | ResultCode Map(VAddr dst_addr, VAddr src_addr, std::size_t size); |
| 40 | ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size); | 40 | ResultCode Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size); |
| 41 | ResultCode MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state, | 41 | ResultCode MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, |
| 42 | MemoryPermission perm); | 42 | KMemoryPermission perm); |
| 43 | ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm); | 43 | ResultCode SetCodeMemoryPermission(VAddr addr, std::size_t size, KMemoryPermission perm); |
| 44 | MemoryInfo QueryInfo(VAddr addr); | 44 | KMemoryInfo QueryInfo(VAddr addr); |
| 45 | ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm); | 45 | ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm); |
| 46 | ResultCode ResetTransferMemory(VAddr addr, std::size_t size); | 46 | ResultCode ResetTransferMemory(VAddr addr, std::size_t size); |
| 47 | ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask, | 47 | ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, |
| 48 | MemoryAttribute value); | 48 | KMemoryAttribute value); |
| 49 | ResultCode SetHeapCapacity(std::size_t new_heap_capacity); | 49 | ResultCode SetHeapCapacity(std::size_t new_heap_capacity); |
| 50 | ResultVal<VAddr> SetHeapSize(std::size_t size); | 50 | ResultVal<VAddr> SetHeapSize(std::size_t size); |
| 51 | ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, | 51 | ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, |
| 52 | bool is_map_only, VAddr region_start, | 52 | bool is_map_only, VAddr region_start, |
| 53 | std::size_t region_num_pages, MemoryState state, | 53 | std::size_t region_num_pages, KMemoryState state, |
| 54 | MemoryPermission perm, PAddr map_addr = 0); | 54 | KMemoryPermission perm, PAddr map_addr = 0); |
| 55 | ResultCode LockForDeviceAddressSpace(VAddr addr, std::size_t size); | 55 | ResultCode LockForDeviceAddressSpace(VAddr addr, std::size_t size); |
| 56 | ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size); | 56 | ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size); |
| 57 | 57 | ||
| @@ -72,47 +72,49 @@ private: | |||
| 72 | ChangePermissionsAndRefresh, | 72 | ChangePermissionsAndRefresh, |
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | static constexpr MemoryAttribute DefaultMemoryIgnoreAttr = | 75 | static constexpr KMemoryAttribute DefaultMemoryIgnoreAttr = KMemoryAttribute::DontCareMask | |
| 76 | MemoryAttribute::DontCareMask | MemoryAttribute::IpcLocked | MemoryAttribute::DeviceShared; | 76 | KMemoryAttribute::IpcLocked | |
| 77 | KMemoryAttribute::DeviceShared; | ||
| 77 | 78 | ||
| 78 | ResultCode InitializeMemoryLayout(VAddr start, VAddr end); | 79 | ResultCode InitializeMemoryLayout(VAddr start, VAddr end); |
| 79 | ResultCode MapPages(VAddr addr, const PageLinkedList& page_linked_list, MemoryPermission perm); | 80 | ResultCode MapPages(VAddr addr, const KPageLinkedList& page_linked_list, |
| 80 | void MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, VAddr end); | 81 | KMemoryPermission perm); |
| 82 | void MapPhysicalMemory(KPageLinkedList& page_linked_list, VAddr start, VAddr end); | ||
| 81 | bool IsRegionMapped(VAddr address, u64 size); | 83 | bool IsRegionMapped(VAddr address, u64 size); |
| 82 | bool IsRegionContiguous(VAddr addr, u64 size) const; | 84 | bool IsRegionContiguous(VAddr addr, u64 size) const; |
| 83 | void AddRegionToPages(VAddr start, std::size_t num_pages, PageLinkedList& page_linked_list); | 85 | void AddRegionToPages(VAddr start, std::size_t num_pages, KPageLinkedList& page_linked_list); |
| 84 | MemoryInfo QueryInfoImpl(VAddr addr); | 86 | KMemoryInfo QueryInfoImpl(VAddr addr); |
| 85 | VAddr AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, u64 needed_num_pages, | 87 | VAddr AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, u64 needed_num_pages, |
| 86 | std::size_t align); | 88 | std::size_t align); |
| 87 | ResultCode Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group, | 89 | ResultCode Operate(VAddr addr, std::size_t num_pages, const KPageLinkedList& page_group, |
| 88 | OperationType operation); | 90 | OperationType operation); |
| 89 | ResultCode Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm, | 91 | ResultCode Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm, |
| 90 | OperationType operation, PAddr map_addr = 0); | 92 | OperationType operation, PAddr map_addr = 0); |
| 91 | constexpr VAddr GetRegionAddress(MemoryState state) const; | 93 | constexpr VAddr GetRegionAddress(KMemoryState state) const; |
| 92 | constexpr std::size_t GetRegionSize(MemoryState state) const; | 94 | constexpr std::size_t GetRegionSize(KMemoryState state) const; |
| 93 | constexpr bool CanContain(VAddr addr, std::size_t size, MemoryState state) const; | 95 | constexpr bool CanContain(VAddr addr, std::size_t size, KMemoryState state) const; |
| 94 | 96 | ||
| 95 | constexpr ResultCode CheckMemoryState(const MemoryInfo& info, MemoryState state_mask, | 97 | constexpr ResultCode CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask, |
| 96 | MemoryState state, MemoryPermission perm_mask, | 98 | KMemoryState state, KMemoryPermission perm_mask, |
| 97 | MemoryPermission perm, MemoryAttribute attr_mask, | 99 | KMemoryPermission perm, KMemoryAttribute attr_mask, |
| 98 | MemoryAttribute attr) const; | 100 | KMemoryAttribute attr) const; |
| 99 | ResultCode CheckMemoryState(MemoryState* out_state, MemoryPermission* out_perm, | 101 | ResultCode CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm, |
| 100 | MemoryAttribute* out_attr, VAddr addr, std::size_t size, | 102 | KMemoryAttribute* out_attr, VAddr addr, std::size_t size, |
| 101 | MemoryState state_mask, MemoryState state, | 103 | KMemoryState state_mask, KMemoryState state, |
| 102 | MemoryPermission perm_mask, MemoryPermission perm, | 104 | KMemoryPermission perm_mask, KMemoryPermission perm, |
| 103 | MemoryAttribute attr_mask, MemoryAttribute attr, | 105 | KMemoryAttribute attr_mask, KMemoryAttribute attr, |
| 104 | MemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr); | 106 | KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr); |
| 105 | ResultCode CheckMemoryState(VAddr addr, std::size_t size, MemoryState state_mask, | 107 | ResultCode CheckMemoryState(VAddr addr, std::size_t size, KMemoryState state_mask, |
| 106 | MemoryState state, MemoryPermission perm_mask, | 108 | KMemoryState state, KMemoryPermission perm_mask, |
| 107 | MemoryPermission perm, MemoryAttribute attr_mask, | 109 | KMemoryPermission perm, KMemoryAttribute attr_mask, |
| 108 | MemoryAttribute attr, | 110 | KMemoryAttribute attr, |
| 109 | MemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) { | 111 | KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) { |
| 110 | return CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask, | 112 | return CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask, |
| 111 | perm, attr_mask, attr, ignore_attr); | 113 | perm, attr_mask, attr, ignore_attr); |
| 112 | } | 114 | } |
| 113 | 115 | ||
| 114 | std::recursive_mutex page_table_lock; | 116 | std::recursive_mutex page_table_lock; |
| 115 | std::unique_ptr<MemoryBlockManager> block_manager; | 117 | std::unique_ptr<KMemoryBlockManager> block_manager; |
| 116 | 118 | ||
| 117 | public: | 119 | public: |
| 118 | constexpr VAddr GetAddressSpaceStart() const { | 120 | constexpr VAddr GetAddressSpaceStart() const { |
| @@ -212,7 +214,7 @@ public: | |||
| 212 | return !IsOutsideASLRRegion(address, size); | 214 | return !IsOutsideASLRRegion(address, size); |
| 213 | } | 215 | } |
| 214 | constexpr PAddr GetPhysicalAddr(VAddr addr) { | 216 | constexpr PAddr GetPhysicalAddr(VAddr addr) { |
| 215 | return page_table_impl.backing_addr[addr >> Memory::PageBits] + addr; | 217 | return page_table_impl.backing_addr[addr >> PageBits] + addr; |
| 216 | } | 218 | } |
| 217 | 219 | ||
| 218 | private: | 220 | private: |
| @@ -267,11 +269,11 @@ private: | |||
| 267 | bool is_kernel{}; | 269 | bool is_kernel{}; |
| 268 | bool is_aslr_enabled{}; | 270 | bool is_aslr_enabled{}; |
| 269 | 271 | ||
| 270 | MemoryManager::Pool memory_pool{MemoryManager::Pool::Application}; | 272 | KMemoryManager::Pool memory_pool{KMemoryManager::Pool::Application}; |
| 271 | 273 | ||
| 272 | Common::PageTable page_table_impl; | 274 | Common::PageTable page_table_impl; |
| 273 | 275 | ||
| 274 | Core::System& system; | 276 | Core::System& system; |
| 275 | }; | 277 | }; |
| 276 | 278 | ||
| 277 | } // namespace Kernel::Memory | 279 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index 2eadd51d7..9b14f42b5 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp | |||
| @@ -4,33 +4,32 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/hle/kernel/k_page_table.h" | ||
| 7 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | 8 | #include "core/hle/kernel/k_scoped_resource_reservation.h" |
| 9 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 8 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 9 | #include "core/hle/kernel/memory/page_table.h" | ||
| 10 | #include "core/hle/kernel/shared_memory.h" | ||
| 11 | 11 | ||
| 12 | namespace Kernel { | 12 | namespace Kernel { |
| 13 | 13 | ||
| 14 | SharedMemory::SharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory) | 14 | KSharedMemory::KSharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory) |
| 15 | : Object{kernel}, device_memory{device_memory} {} | 15 | : Object{kernel}, device_memory{device_memory} {} |
| 16 | 16 | ||
| 17 | SharedMemory::~SharedMemory() { | 17 | KSharedMemory::~KSharedMemory() { |
| 18 | kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); | 18 | kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | std::shared_ptr<SharedMemory> SharedMemory::Create( | 21 | std::shared_ptr<KSharedMemory> KSharedMemory::Create( |
| 22 | KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process, | 22 | KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process, |
| 23 | Memory::PageLinkedList&& page_list, Memory::MemoryPermission owner_permission, | 23 | KPageLinkedList&& page_list, KMemoryPermission owner_permission, |
| 24 | Memory::MemoryPermission user_permission, PAddr physical_address, std::size_t size, | 24 | KMemoryPermission user_permission, PAddr physical_address, std::size_t size, std::string name) { |
| 25 | std::string name) { | ||
| 26 | 25 | ||
| 27 | const auto resource_limit = kernel.GetSystemResourceLimit(); | 26 | const auto resource_limit = kernel.GetSystemResourceLimit(); |
| 28 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | 27 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, |
| 29 | size); | 28 | size); |
| 30 | ASSERT(memory_reservation.Succeeded()); | 29 | ASSERT(memory_reservation.Succeeded()); |
| 31 | 30 | ||
| 32 | std::shared_ptr<SharedMemory> shared_memory{ | 31 | std::shared_ptr<KSharedMemory> shared_memory{ |
| 33 | std::make_shared<SharedMemory>(kernel, device_memory)}; | 32 | std::make_shared<KSharedMemory>(kernel, device_memory)}; |
| 34 | 33 | ||
| 35 | shared_memory->owner_process = owner_process; | 34 | shared_memory->owner_process = owner_process; |
| 36 | shared_memory->page_list = std::move(page_list); | 35 | shared_memory->page_list = std::move(page_list); |
| @@ -44,22 +43,22 @@ std::shared_ptr<SharedMemory> SharedMemory::Create( | |||
| 44 | return shared_memory; | 43 | return shared_memory; |
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | ResultCode SharedMemory::Map(Process& target_process, VAddr address, std::size_t size, | 46 | ResultCode KSharedMemory::Map(Process& target_process, VAddr address, std::size_t size, |
| 48 | Memory::MemoryPermission permissions) { | 47 | KMemoryPermission permissions) { |
| 49 | const u64 page_count{(size + Memory::PageSize - 1) / Memory::PageSize}; | 48 | const u64 page_count{(size + PageSize - 1) / PageSize}; |
| 50 | 49 | ||
| 51 | if (page_list.GetNumPages() != page_count) { | 50 | if (page_list.GetNumPages() != page_count) { |
| 52 | UNIMPLEMENTED_MSG("Page count does not match"); | 51 | UNIMPLEMENTED_MSG("Page count does not match"); |
| 53 | } | 52 | } |
| 54 | 53 | ||
| 55 | const Memory::MemoryPermission expected = | 54 | const KMemoryPermission expected = |
| 56 | &target_process == owner_process ? owner_permission : user_permission; | 55 | &target_process == owner_process ? owner_permission : user_permission; |
| 57 | 56 | ||
| 58 | if (permissions != expected) { | 57 | if (permissions != expected) { |
| 59 | UNIMPLEMENTED_MSG("Permission does not match"); | 58 | UNIMPLEMENTED_MSG("Permission does not match"); |
| 60 | } | 59 | } |
| 61 | 60 | ||
| 62 | return target_process.PageTable().MapPages(address, page_list, Memory::MemoryState::Shared, | 61 | return target_process.PageTable().MapPages(address, page_list, KMemoryState::Shared, |
| 63 | permissions); | 62 | permissions); |
| 64 | } | 63 | } |
| 65 | 64 | ||
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 623bd8b11..016e34be5 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "core/device_memory.h" | 11 | #include "core/device_memory.h" |
| 12 | #include "core/hle/kernel/memory/memory_block.h" | 12 | #include "core/hle/kernel/k_memory_block.h" |
| 13 | #include "core/hle/kernel/memory/page_linked_list.h" | 13 | #include "core/hle/kernel/k_page_linked_list.h" |
| 14 | #include "core/hle/kernel/object.h" | 14 | #include "core/hle/kernel/object.h" |
| 15 | #include "core/hle/kernel/process.h" | 15 | #include "core/hle/kernel/process.h" |
| 16 | #include "core/hle/result.h" | 16 | #include "core/hle/result.h" |
| @@ -19,15 +19,15 @@ namespace Kernel { | |||
| 19 | 19 | ||
| 20 | class KernelCore; | 20 | class KernelCore; |
| 21 | 21 | ||
| 22 | class SharedMemory final : public Object { | 22 | class KSharedMemory final : public Object { |
| 23 | public: | 23 | public: |
| 24 | explicit SharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory); | 24 | explicit KSharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory); |
| 25 | ~SharedMemory() override; | 25 | ~KSharedMemory() override; |
| 26 | 26 | ||
| 27 | static std::shared_ptr<SharedMemory> Create( | 27 | static std::shared_ptr<KSharedMemory> Create( |
| 28 | KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process, | 28 | KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process, |
| 29 | Memory::PageLinkedList&& page_list, Memory::MemoryPermission owner_permission, | 29 | KPageLinkedList&& page_list, KMemoryPermission owner_permission, |
| 30 | Memory::MemoryPermission user_permission, PAddr physical_address, std::size_t size, | 30 | KMemoryPermission user_permission, PAddr physical_address, std::size_t size, |
| 31 | std::string name); | 31 | std::string name); |
| 32 | 32 | ||
| 33 | std::string GetTypeName() const override { | 33 | std::string GetTypeName() const override { |
| @@ -51,7 +51,7 @@ public: | |||
| 51 | * @param permissions Memory block map permissions (specified by SVC field) | 51 | * @param permissions Memory block map permissions (specified by SVC field) |
| 52 | */ | 52 | */ |
| 53 | ResultCode Map(Process& target_process, VAddr address, std::size_t size, | 53 | ResultCode Map(Process& target_process, VAddr address, std::size_t size, |
| 54 | Memory::MemoryPermission permissions); | 54 | KMemoryPermission permissions); |
| 55 | 55 | ||
| 56 | /** | 56 | /** |
| 57 | * Gets a pointer to the shared memory block | 57 | * Gets a pointer to the shared memory block |
| @@ -76,9 +76,9 @@ public: | |||
| 76 | private: | 76 | private: |
| 77 | Core::DeviceMemory& device_memory; | 77 | Core::DeviceMemory& device_memory; |
| 78 | Process* owner_process{}; | 78 | Process* owner_process{}; |
| 79 | Memory::PageLinkedList page_list; | 79 | KPageLinkedList page_list; |
| 80 | Memory::MemoryPermission owner_permission{}; | 80 | KMemoryPermission owner_permission{}; |
| 81 | Memory::MemoryPermission user_permission{}; | 81 | KMemoryPermission user_permission{}; |
| 82 | PAddr physical_address{}; | 82 | PAddr physical_address{}; |
| 83 | std::size_t size{}; | 83 | std::size_t size{}; |
| 84 | std::string name; | 84 | std::string name; |
diff --git a/src/core/hle/kernel/memory/slab_heap.h b/src/core/hle/kernel/k_slab_heap.h index 465eaddb3..aa4471d2f 100644 --- a/src/core/hle/kernel/memory/slab_heap.h +++ b/src/core/hle/kernel/k_slab_heap.h | |||
| @@ -2,9 +2,6 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #pragma once | 5 | #pragma once |
| 9 | 6 | ||
| 10 | #include <atomic> | 7 | #include <atomic> |
| @@ -12,17 +9,17 @@ | |||
| 12 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 13 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 14 | 11 | ||
| 15 | namespace Kernel::Memory { | 12 | namespace Kernel { |
| 16 | 13 | ||
| 17 | namespace impl { | 14 | namespace impl { |
| 18 | 15 | ||
| 19 | class SlabHeapImpl final : NonCopyable { | 16 | class KSlabHeapImpl final : NonCopyable { |
| 20 | public: | 17 | public: |
| 21 | struct Node { | 18 | struct Node { |
| 22 | Node* next{}; | 19 | Node* next{}; |
| 23 | }; | 20 | }; |
| 24 | 21 | ||
| 25 | constexpr SlabHeapImpl() = default; | 22 | constexpr KSlabHeapImpl() = default; |
| 26 | 23 | ||
| 27 | void Initialize(std::size_t size) { | 24 | void Initialize(std::size_t size) { |
| 28 | ASSERT(head == nullptr); | 25 | ASSERT(head == nullptr); |
| @@ -65,9 +62,9 @@ private: | |||
| 65 | 62 | ||
| 66 | } // namespace impl | 63 | } // namespace impl |
| 67 | 64 | ||
| 68 | class SlabHeapBase : NonCopyable { | 65 | class KSlabHeapBase : NonCopyable { |
| 69 | public: | 66 | public: |
| 70 | constexpr SlabHeapBase() = default; | 67 | constexpr KSlabHeapBase() = default; |
| 71 | 68 | ||
| 72 | constexpr bool Contains(uintptr_t addr) const { | 69 | constexpr bool Contains(uintptr_t addr) const { |
| 73 | return start <= addr && addr < end; | 70 | return start <= addr && addr < end; |
| @@ -126,7 +123,7 @@ public: | |||
| 126 | } | 123 | } |
| 127 | 124 | ||
| 128 | private: | 125 | private: |
| 129 | using Impl = impl::SlabHeapImpl; | 126 | using Impl = impl::KSlabHeapImpl; |
| 130 | 127 | ||
| 131 | Impl impl; | 128 | Impl impl; |
| 132 | uintptr_t peak{}; | 129 | uintptr_t peak{}; |
| @@ -135,9 +132,9 @@ private: | |||
| 135 | }; | 132 | }; |
| 136 | 133 | ||
| 137 | template <typename T> | 134 | template <typename T> |
| 138 | class SlabHeap final : public SlabHeapBase { | 135 | class KSlabHeap final : public KSlabHeapBase { |
| 139 | public: | 136 | public: |
| 140 | constexpr SlabHeap() : SlabHeapBase() {} | 137 | constexpr KSlabHeap() : KSlabHeapBase() {} |
| 141 | 138 | ||
| 142 | void Initialize(void* memory, std::size_t memory_size) { | 139 | void Initialize(void* memory, std::size_t memory_size) { |
| 143 | InitializeImpl(sizeof(T), memory, memory_size); | 140 | InitializeImpl(sizeof(T), memory, memory_size); |
| @@ -160,4 +157,4 @@ public: | |||
| 160 | } | 157 | } |
| 161 | }; | 158 | }; |
| 162 | 159 | ||
| 163 | } // namespace Kernel::Memory | 160 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_spin_lock.cpp b/src/core/hle/kernel/k_spin_lock.cpp new file mode 100644 index 000000000..4412aa4bb --- /dev/null +++ b/src/core/hle/kernel/k_spin_lock.cpp | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/k_spin_lock.h" | ||
| 6 | |||
| 7 | #if _MSC_VER | ||
| 8 | #include <intrin.h> | ||
| 9 | #if _M_AMD64 | ||
| 10 | #define __x86_64__ 1 | ||
| 11 | #endif | ||
| 12 | #if _M_ARM64 | ||
| 13 | #define __aarch64__ 1 | ||
| 14 | #endif | ||
| 15 | #else | ||
| 16 | #if __x86_64__ | ||
| 17 | #include <xmmintrin.h> | ||
| 18 | #endif | ||
| 19 | #endif | ||
| 20 | |||
| 21 | namespace { | ||
| 22 | |||
| 23 | void ThreadPause() { | ||
| 24 | #if __x86_64__ | ||
| 25 | _mm_pause(); | ||
| 26 | #elif __aarch64__ && _MSC_VER | ||
| 27 | __yield(); | ||
| 28 | #elif __aarch64__ | ||
| 29 | asm("yield"); | ||
| 30 | #endif | ||
| 31 | } | ||
| 32 | |||
| 33 | } // namespace | ||
| 34 | |||
| 35 | namespace Kernel { | ||
| 36 | |||
| 37 | void KSpinLock::Lock() { | ||
| 38 | while (lck.test_and_set(std::memory_order_acquire)) { | ||
| 39 | ThreadPause(); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | void KSpinLock::Unlock() { | ||
| 44 | lck.clear(std::memory_order_release); | ||
| 45 | } | ||
| 46 | |||
| 47 | bool KSpinLock::TryLock() { | ||
| 48 | if (lck.test_and_set(std::memory_order_acquire)) { | ||
| 49 | return false; | ||
| 50 | } | ||
| 51 | return true; | ||
| 52 | } | ||
| 53 | |||
| 54 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_spin_lock.h b/src/core/hle/kernel/k_spin_lock.h new file mode 100644 index 000000000..12c4b2e88 --- /dev/null +++ b/src/core/hle/kernel/k_spin_lock.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <atomic> | ||
| 8 | |||
| 9 | #include "core/hle/kernel/k_scoped_lock.h" | ||
| 10 | |||
| 11 | namespace Kernel { | ||
| 12 | |||
| 13 | class KSpinLock { | ||
| 14 | public: | ||
| 15 | KSpinLock() = default; | ||
| 16 | |||
| 17 | KSpinLock(const KSpinLock&) = delete; | ||
| 18 | KSpinLock& operator=(const KSpinLock&) = delete; | ||
| 19 | |||
| 20 | KSpinLock(KSpinLock&&) = delete; | ||
| 21 | KSpinLock& operator=(KSpinLock&&) = delete; | ||
| 22 | |||
| 23 | void Lock(); | ||
| 24 | void Unlock(); | ||
| 25 | [[nodiscard]] bool TryLock(); | ||
| 26 | |||
| 27 | private: | ||
| 28 | std::atomic_flag lck = ATOMIC_FLAG_INIT; | ||
| 29 | }; | ||
| 30 | |||
| 31 | using KScopedSpinLock = KScopedLock<KSpinLock>; | ||
| 32 | |||
| 33 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/memory/system_control.cpp b/src/core/hle/kernel/k_system_control.cpp index 11d204bc2..aa1682f69 100644 --- a/src/core/hle/kernel/memory/system_control.cpp +++ b/src/core/hle/kernel/k_system_control.cpp | |||
| @@ -1,12 +1,13 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <random> | 5 | #include <random> |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/memory/system_control.h" | 7 | #include "core/hle/kernel/k_system_control.h" |
| 8 | |||
| 9 | namespace Kernel { | ||
| 8 | 10 | ||
| 9 | namespace Kernel::Memory::SystemControl { | ||
| 10 | namespace { | 11 | namespace { |
| 11 | template <typename F> | 12 | template <typename F> |
| 12 | u64 GenerateUniformRange(u64 min, u64 max, F f) { | 13 | u64 GenerateUniformRange(u64 min, u64 max, F f) { |
| @@ -25,16 +26,17 @@ u64 GenerateUniformRange(u64 min, u64 max, F f) { | |||
| 25 | } | 26 | } |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | u64 GenerateRandomU64ForInit() { | 29 | } // Anonymous namespace |
| 30 | |||
| 31 | u64 KSystemControl::GenerateRandomU64() { | ||
| 29 | static std::random_device device; | 32 | static std::random_device device; |
| 30 | static std::mt19937 gen(device()); | 33 | static std::mt19937 gen(device()); |
| 31 | static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); | 34 | static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max()); |
| 32 | return distribution(gen); | 35 | return distribution(gen); |
| 33 | } | 36 | } |
| 34 | } // Anonymous namespace | ||
| 35 | 37 | ||
| 36 | u64 GenerateRandomRange(u64 min, u64 max) { | 38 | u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) { |
| 37 | return GenerateUniformRange(min, max, GenerateRandomU64ForInit); | 39 | return GenerateUniformRange(min, max, GenerateRandomU64); |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 40 | } // namespace Kernel::Memory::SystemControl | 42 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_system_control.h b/src/core/hle/kernel/k_system_control.h new file mode 100644 index 000000000..1d5b64ffa --- /dev/null +++ b/src/core/hle/kernel/k_system_control.h | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | |||
| 11 | class KSystemControl { | ||
| 12 | public: | ||
| 13 | KSystemControl() = default; | ||
| 14 | |||
| 15 | static u64 GenerateRandomRange(u64 min, u64 max); | ||
| 16 | static u64 GenerateRandomU64(); | ||
| 17 | }; | ||
| 18 | |||
| 19 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index e5620da5a..1661afbd9 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -20,13 +20,13 @@ | |||
| 20 | #include "core/hardware_properties.h" | 20 | #include "core/hardware_properties.h" |
| 21 | #include "core/hle/kernel/handle_table.h" | 21 | #include "core/hle/kernel/handle_table.h" |
| 22 | #include "core/hle/kernel/k_condition_variable.h" | 22 | #include "core/hle/kernel/k_condition_variable.h" |
| 23 | #include "core/hle/kernel/k_memory_layout.h" | ||
| 23 | #include "core/hle/kernel/k_resource_limit.h" | 24 | #include "core/hle/kernel/k_resource_limit.h" |
| 24 | #include "core/hle/kernel/k_scheduler.h" | 25 | #include "core/hle/kernel/k_scheduler.h" |
| 25 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | 26 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" |
| 26 | #include "core/hle/kernel/k_thread.h" | 27 | #include "core/hle/kernel/k_thread.h" |
| 27 | #include "core/hle/kernel/k_thread_queue.h" | 28 | #include "core/hle/kernel/k_thread_queue.h" |
| 28 | #include "core/hle/kernel/kernel.h" | 29 | #include "core/hle/kernel/kernel.h" |
| 29 | #include "core/hle/kernel/memory/memory_layout.h" | ||
| 30 | #include "core/hle/kernel/object.h" | 30 | #include "core/hle/kernel/object.h" |
| 31 | #include "core/hle/kernel/process.h" | 31 | #include "core/hle/kernel/process.h" |
| 32 | #include "core/hle/kernel/svc_results.h" | 32 | #include "core/hle/kernel/svc_results.h" |
| @@ -782,7 +782,7 @@ void KThread::AddWaiterImpl(KThread* thread) { | |||
| 782 | } | 782 | } |
| 783 | 783 | ||
| 784 | // Keep track of how many kernel waiters we have. | 784 | // Keep track of how many kernel waiters we have. |
| 785 | if (Memory::IsKernelAddressKey(thread->GetAddressKey())) { | 785 | if (IsKernelAddressKey(thread->GetAddressKey())) { |
| 786 | ASSERT((num_kernel_waiters++) >= 0); | 786 | ASSERT((num_kernel_waiters++) >= 0); |
| 787 | } | 787 | } |
| 788 | 788 | ||
| @@ -795,7 +795,7 @@ void KThread::RemoveWaiterImpl(KThread* thread) { | |||
| 795 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 795 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 796 | 796 | ||
| 797 | // Keep track of how many kernel waiters we have. | 797 | // Keep track of how many kernel waiters we have. |
| 798 | if (Memory::IsKernelAddressKey(thread->GetAddressKey())) { | 798 | if (IsKernelAddressKey(thread->GetAddressKey())) { |
| 799 | ASSERT((num_kernel_waiters--) > 0); | 799 | ASSERT((num_kernel_waiters--) > 0); |
| 800 | } | 800 | } |
| 801 | 801 | ||
| @@ -870,7 +870,7 @@ KThread* KThread::RemoveWaiterByKey(s32* out_num_waiters, VAddr key) { | |||
| 870 | KThread* thread = std::addressof(*it); | 870 | KThread* thread = std::addressof(*it); |
| 871 | 871 | ||
| 872 | // Keep track of how many kernel waiters we have. | 872 | // Keep track of how many kernel waiters we have. |
| 873 | if (Memory::IsKernelAddressKey(thread->GetAddressKey())) { | 873 | if (IsKernelAddressKey(thread->GetAddressKey())) { |
| 874 | ASSERT((num_kernel_waiters--) > 0); | 874 | ASSERT((num_kernel_waiters--) > 0); |
| 875 | } | 875 | } |
| 876 | it = waiter_list.erase(it); | 876 | it = waiter_list.erase(it); |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 39c5182c5..331cf3a60 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -27,17 +27,17 @@ | |||
| 27 | #include "core/hardware_properties.h" | 27 | #include "core/hardware_properties.h" |
| 28 | #include "core/hle/kernel/client_port.h" | 28 | #include "core/hle/kernel/client_port.h" |
| 29 | #include "core/hle/kernel/handle_table.h" | 29 | #include "core/hle/kernel/handle_table.h" |
| 30 | #include "core/hle/kernel/k_memory_layout.h" | ||
| 31 | #include "core/hle/kernel/k_memory_manager.h" | ||
| 30 | #include "core/hle/kernel/k_resource_limit.h" | 32 | #include "core/hle/kernel/k_resource_limit.h" |
| 31 | #include "core/hle/kernel/k_scheduler.h" | 33 | #include "core/hle/kernel/k_scheduler.h" |
| 34 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 35 | #include "core/hle/kernel/k_slab_heap.h" | ||
| 32 | #include "core/hle/kernel/k_thread.h" | 36 | #include "core/hle/kernel/k_thread.h" |
| 33 | #include "core/hle/kernel/kernel.h" | 37 | #include "core/hle/kernel/kernel.h" |
| 34 | #include "core/hle/kernel/memory/memory_layout.h" | ||
| 35 | #include "core/hle/kernel/memory/memory_manager.h" | ||
| 36 | #include "core/hle/kernel/memory/slab_heap.h" | ||
| 37 | #include "core/hle/kernel/physical_core.h" | 38 | #include "core/hle/kernel/physical_core.h" |
| 38 | #include "core/hle/kernel/process.h" | 39 | #include "core/hle/kernel/process.h" |
| 39 | #include "core/hle/kernel/service_thread.h" | 40 | #include "core/hle/kernel/service_thread.h" |
| 40 | #include "core/hle/kernel/shared_memory.h" | ||
| 41 | #include "core/hle/kernel/svc_results.h" | 41 | #include "core/hle/kernel/svc_results.h" |
| 42 | #include "core/hle/kernel/time_manager.h" | 42 | #include "core/hle/kernel/time_manager.h" |
| 43 | #include "core/hle/lock.h" | 43 | #include "core/hle/lock.h" |
| @@ -271,7 +271,7 @@ struct KernelCore::Impl { | |||
| 271 | 271 | ||
| 272 | void InitializeMemoryLayout() { | 272 | void InitializeMemoryLayout() { |
| 273 | // Initialize memory layout | 273 | // Initialize memory layout |
| 274 | constexpr Memory::MemoryLayout layout{Memory::MemoryLayout::GetDefaultLayout()}; | 274 | constexpr KMemoryLayout layout{KMemoryLayout::GetDefaultLayout()}; |
| 275 | constexpr std::size_t hid_size{0x40000}; | 275 | constexpr std::size_t hid_size{0x40000}; |
| 276 | constexpr std::size_t font_size{0x1100000}; | 276 | constexpr std::size_t font_size{0x1100000}; |
| 277 | constexpr std::size_t irs_size{0x8000}; | 277 | constexpr std::size_t irs_size{0x8000}; |
| @@ -282,36 +282,36 @@ struct KernelCore::Impl { | |||
| 282 | constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size}; | 282 | constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size}; |
| 283 | 283 | ||
| 284 | // Initialize memory manager | 284 | // Initialize memory manager |
| 285 | memory_manager = std::make_unique<Memory::MemoryManager>(); | 285 | memory_manager = std::make_unique<KMemoryManager>(); |
| 286 | memory_manager->InitializeManager(Memory::MemoryManager::Pool::Application, | 286 | memory_manager->InitializeManager(KMemoryManager::Pool::Application, |
| 287 | layout.Application().StartAddress(), | 287 | layout.Application().StartAddress(), |
| 288 | layout.Application().EndAddress()); | 288 | layout.Application().EndAddress()); |
| 289 | memory_manager->InitializeManager(Memory::MemoryManager::Pool::Applet, | 289 | memory_manager->InitializeManager(KMemoryManager::Pool::Applet, |
| 290 | layout.Applet().StartAddress(), | 290 | layout.Applet().StartAddress(), |
| 291 | layout.Applet().EndAddress()); | 291 | layout.Applet().EndAddress()); |
| 292 | memory_manager->InitializeManager(Memory::MemoryManager::Pool::System, | 292 | memory_manager->InitializeManager(KMemoryManager::Pool::System, |
| 293 | layout.System().StartAddress(), | 293 | layout.System().StartAddress(), |
| 294 | layout.System().EndAddress()); | 294 | layout.System().EndAddress()); |
| 295 | 295 | ||
| 296 | hid_shared_mem = Kernel::SharedMemory::Create( | 296 | hid_shared_mem = Kernel::KSharedMemory::Create( |
| 297 | system.Kernel(), system.DeviceMemory(), nullptr, | 297 | system.Kernel(), system.DeviceMemory(), nullptr, {hid_addr, hid_size / PageSize}, |
| 298 | {hid_addr, hid_size / Memory::PageSize}, Memory::MemoryPermission::None, | 298 | KMemoryPermission::None, KMemoryPermission::Read, hid_addr, hid_size, |
| 299 | Memory::MemoryPermission::Read, hid_addr, hid_size, "HID:SharedMemory"); | 299 | "HID:SharedMemory"); |
| 300 | font_shared_mem = Kernel::SharedMemory::Create( | 300 | font_shared_mem = Kernel::KSharedMemory::Create( |
| 301 | system.Kernel(), system.DeviceMemory(), nullptr, | 301 | system.Kernel(), system.DeviceMemory(), nullptr, {font_pa, font_size / PageSize}, |
| 302 | {font_pa, font_size / Memory::PageSize}, Memory::MemoryPermission::None, | 302 | KMemoryPermission::None, KMemoryPermission::Read, font_pa, font_size, |
| 303 | Memory::MemoryPermission::Read, font_pa, font_size, "Font:SharedMemory"); | 303 | "Font:SharedMemory"); |
| 304 | irs_shared_mem = Kernel::SharedMemory::Create( | 304 | irs_shared_mem = Kernel::KSharedMemory::Create( |
| 305 | system.Kernel(), system.DeviceMemory(), nullptr, | 305 | system.Kernel(), system.DeviceMemory(), nullptr, {irs_addr, irs_size / PageSize}, |
| 306 | {irs_addr, irs_size / Memory::PageSize}, Memory::MemoryPermission::None, | 306 | KMemoryPermission::None, KMemoryPermission::Read, irs_addr, irs_size, |
| 307 | Memory::MemoryPermission::Read, irs_addr, irs_size, "IRS:SharedMemory"); | 307 | "IRS:SharedMemory"); |
| 308 | time_shared_mem = Kernel::SharedMemory::Create( | 308 | time_shared_mem = Kernel::KSharedMemory::Create( |
| 309 | system.Kernel(), system.DeviceMemory(), nullptr, | 309 | system.Kernel(), system.DeviceMemory(), nullptr, {time_addr, time_size / PageSize}, |
| 310 | {time_addr, time_size / Memory::PageSize}, Memory::MemoryPermission::None, | 310 | KMemoryPermission::None, KMemoryPermission::Read, time_addr, time_size, |
| 311 | Memory::MemoryPermission::Read, time_addr, time_size, "Time:SharedMemory"); | 311 | "Time:SharedMemory"); |
| 312 | 312 | ||
| 313 | // Allocate slab heaps | 313 | // Allocate slab heaps |
| 314 | user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>(); | 314 | user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>(); |
| 315 | 315 | ||
| 316 | constexpr u64 user_slab_heap_size{0x1ef000}; | 316 | constexpr u64 user_slab_heap_size{0x1ef000}; |
| 317 | // Reserve slab heaps | 317 | // Reserve slab heaps |
| @@ -353,14 +353,14 @@ struct KernelCore::Impl { | |||
| 353 | std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES}; | 353 | std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES}; |
| 354 | 354 | ||
| 355 | // Kernel memory management | 355 | // Kernel memory management |
| 356 | std::unique_ptr<Memory::MemoryManager> memory_manager; | 356 | std::unique_ptr<KMemoryManager> memory_manager; |
| 357 | std::unique_ptr<Memory::SlabHeap<Memory::Page>> user_slab_heap_pages; | 357 | std::unique_ptr<KSlabHeap<Page>> user_slab_heap_pages; |
| 358 | 358 | ||
| 359 | // Shared memory for services | 359 | // Shared memory for services |
| 360 | std::shared_ptr<Kernel::SharedMemory> hid_shared_mem; | 360 | std::shared_ptr<Kernel::KSharedMemory> hid_shared_mem; |
| 361 | std::shared_ptr<Kernel::SharedMemory> font_shared_mem; | 361 | std::shared_ptr<Kernel::KSharedMemory> font_shared_mem; |
| 362 | std::shared_ptr<Kernel::SharedMemory> irs_shared_mem; | 362 | std::shared_ptr<Kernel::KSharedMemory> irs_shared_mem; |
| 363 | std::shared_ptr<Kernel::SharedMemory> time_shared_mem; | 363 | std::shared_ptr<Kernel::KSharedMemory> time_shared_mem; |
| 364 | 364 | ||
| 365 | // Threads used for services | 365 | // Threads used for services |
| 366 | std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads; | 366 | std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads; |
| @@ -578,51 +578,51 @@ KThread* KernelCore::GetCurrentEmuThread() const { | |||
| 578 | return impl->GetCurrentEmuThread(); | 578 | return impl->GetCurrentEmuThread(); |
| 579 | } | 579 | } |
| 580 | 580 | ||
| 581 | Memory::MemoryManager& KernelCore::MemoryManager() { | 581 | KMemoryManager& KernelCore::MemoryManager() { |
| 582 | return *impl->memory_manager; | 582 | return *impl->memory_manager; |
| 583 | } | 583 | } |
| 584 | 584 | ||
| 585 | const Memory::MemoryManager& KernelCore::MemoryManager() const { | 585 | const KMemoryManager& KernelCore::MemoryManager() const { |
| 586 | return *impl->memory_manager; | 586 | return *impl->memory_manager; |
| 587 | } | 587 | } |
| 588 | 588 | ||
| 589 | Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() { | 589 | KSlabHeap<Page>& KernelCore::GetUserSlabHeapPages() { |
| 590 | return *impl->user_slab_heap_pages; | 590 | return *impl->user_slab_heap_pages; |
| 591 | } | 591 | } |
| 592 | 592 | ||
| 593 | const Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() const { | 593 | const KSlabHeap<Page>& KernelCore::GetUserSlabHeapPages() const { |
| 594 | return *impl->user_slab_heap_pages; | 594 | return *impl->user_slab_heap_pages; |
| 595 | } | 595 | } |
| 596 | 596 | ||
| 597 | Kernel::SharedMemory& KernelCore::GetHidSharedMem() { | 597 | Kernel::KSharedMemory& KernelCore::GetHidSharedMem() { |
| 598 | return *impl->hid_shared_mem; | 598 | return *impl->hid_shared_mem; |
| 599 | } | 599 | } |
| 600 | 600 | ||
| 601 | const Kernel::SharedMemory& KernelCore::GetHidSharedMem() const { | 601 | const Kernel::KSharedMemory& KernelCore::GetHidSharedMem() const { |
| 602 | return *impl->hid_shared_mem; | 602 | return *impl->hid_shared_mem; |
| 603 | } | 603 | } |
| 604 | 604 | ||
| 605 | Kernel::SharedMemory& KernelCore::GetFontSharedMem() { | 605 | Kernel::KSharedMemory& KernelCore::GetFontSharedMem() { |
| 606 | return *impl->font_shared_mem; | 606 | return *impl->font_shared_mem; |
| 607 | } | 607 | } |
| 608 | 608 | ||
| 609 | const Kernel::SharedMemory& KernelCore::GetFontSharedMem() const { | 609 | const Kernel::KSharedMemory& KernelCore::GetFontSharedMem() const { |
| 610 | return *impl->font_shared_mem; | 610 | return *impl->font_shared_mem; |
| 611 | } | 611 | } |
| 612 | 612 | ||
| 613 | Kernel::SharedMemory& KernelCore::GetIrsSharedMem() { | 613 | Kernel::KSharedMemory& KernelCore::GetIrsSharedMem() { |
| 614 | return *impl->irs_shared_mem; | 614 | return *impl->irs_shared_mem; |
| 615 | } | 615 | } |
| 616 | 616 | ||
| 617 | const Kernel::SharedMemory& KernelCore::GetIrsSharedMem() const { | 617 | const Kernel::KSharedMemory& KernelCore::GetIrsSharedMem() const { |
| 618 | return *impl->irs_shared_mem; | 618 | return *impl->irs_shared_mem; |
| 619 | } | 619 | } |
| 620 | 620 | ||
| 621 | Kernel::SharedMemory& KernelCore::GetTimeSharedMem() { | 621 | Kernel::KSharedMemory& KernelCore::GetTimeSharedMem() { |
| 622 | return *impl->time_shared_mem; | 622 | return *impl->time_shared_mem; |
| 623 | } | 623 | } |
| 624 | 624 | ||
| 625 | const Kernel::SharedMemory& KernelCore::GetTimeSharedMem() const { | 625 | const Kernel::KSharedMemory& KernelCore::GetTimeSharedMem() const { |
| 626 | return *impl->time_shared_mem; | 626 | return *impl->time_shared_mem; |
| 627 | } | 627 | } |
| 628 | 628 | ||
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 806a0d986..56906f2da 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | #include "core/arm/cpu_interrupt_handler.h" | 12 | #include "core/arm/cpu_interrupt_handler.h" |
| 13 | #include "core/hardware_properties.h" | 13 | #include "core/hardware_properties.h" |
| 14 | #include "core/hle/kernel/memory/memory_types.h" | 14 | #include "core/hle/kernel/memory_types.h" |
| 15 | #include "core/hle/kernel/object.h" | 15 | #include "core/hle/kernel/object.h" |
| 16 | 16 | ||
| 17 | namespace Core { | 17 | namespace Core { |
| @@ -27,25 +27,23 @@ struct EventType; | |||
| 27 | 27 | ||
| 28 | namespace Kernel { | 28 | namespace Kernel { |
| 29 | 29 | ||
| 30 | namespace Memory { | ||
| 31 | class MemoryManager; | ||
| 32 | template <typename T> | ||
| 33 | class SlabHeap; | ||
| 34 | } // namespace Memory | ||
| 35 | |||
| 36 | class ClientPort; | 30 | class ClientPort; |
| 37 | class GlobalSchedulerContext; | 31 | class GlobalSchedulerContext; |
| 38 | class HandleTable; | 32 | class HandleTable; |
| 39 | class PhysicalCore; | 33 | class KMemoryManager; |
| 40 | class Process; | ||
| 41 | class KResourceLimit; | 34 | class KResourceLimit; |
| 42 | class KScheduler; | 35 | class KScheduler; |
| 43 | class SharedMemory; | 36 | class KSharedMemory; |
| 37 | class KThread; | ||
| 38 | class PhysicalCore; | ||
| 39 | class Process; | ||
| 44 | class ServiceThread; | 40 | class ServiceThread; |
| 45 | class Synchronization; | 41 | class Synchronization; |
| 46 | class KThread; | ||
| 47 | class TimeManager; | 42 | class TimeManager; |
| 48 | 43 | ||
| 44 | template <typename T> | ||
| 45 | class KSlabHeap; | ||
| 46 | |||
| 49 | using EmuThreadHandle = uintptr_t; | 47 | using EmuThreadHandle = uintptr_t; |
| 50 | constexpr EmuThreadHandle EmuThreadHandleInvalid{}; | 48 | constexpr EmuThreadHandle EmuThreadHandleInvalid{}; |
| 51 | constexpr EmuThreadHandle EmuThreadHandleReserved{1ULL << 63}; | 49 | constexpr EmuThreadHandle EmuThreadHandleReserved{1ULL << 63}; |
| @@ -178,40 +176,40 @@ public: | |||
| 178 | void RegisterHostThread(); | 176 | void RegisterHostThread(); |
| 179 | 177 | ||
| 180 | /// Gets the virtual memory manager for the kernel. | 178 | /// Gets the virtual memory manager for the kernel. |
| 181 | Memory::MemoryManager& MemoryManager(); | 179 | KMemoryManager& MemoryManager(); |
| 182 | 180 | ||
| 183 | /// Gets the virtual memory manager for the kernel. | 181 | /// Gets the virtual memory manager for the kernel. |
| 184 | const Memory::MemoryManager& MemoryManager() const; | 182 | const KMemoryManager& MemoryManager() const; |
| 185 | 183 | ||
| 186 | /// Gets the slab heap allocated for user space pages. | 184 | /// Gets the slab heap allocated for user space pages. |
| 187 | Memory::SlabHeap<Memory::Page>& GetUserSlabHeapPages(); | 185 | KSlabHeap<Page>& GetUserSlabHeapPages(); |
| 188 | 186 | ||
| 189 | /// Gets the slab heap allocated for user space pages. | 187 | /// Gets the slab heap allocated for user space pages. |
| 190 | const Memory::SlabHeap<Memory::Page>& GetUserSlabHeapPages() const; | 188 | const KSlabHeap<Page>& GetUserSlabHeapPages() const; |
| 191 | 189 | ||
| 192 | /// Gets the shared memory object for HID services. | 190 | /// Gets the shared memory object for HID services. |
| 193 | Kernel::SharedMemory& GetHidSharedMem(); | 191 | Kernel::KSharedMemory& GetHidSharedMem(); |
| 194 | 192 | ||
| 195 | /// Gets the shared memory object for HID services. | 193 | /// Gets the shared memory object for HID services. |
| 196 | const Kernel::SharedMemory& GetHidSharedMem() const; | 194 | const Kernel::KSharedMemory& GetHidSharedMem() const; |
| 197 | 195 | ||
| 198 | /// Gets the shared memory object for font services. | 196 | /// Gets the shared memory object for font services. |
| 199 | Kernel::SharedMemory& GetFontSharedMem(); | 197 | Kernel::KSharedMemory& GetFontSharedMem(); |
| 200 | 198 | ||
| 201 | /// Gets the shared memory object for font services. | 199 | /// Gets the shared memory object for font services. |
| 202 | const Kernel::SharedMemory& GetFontSharedMem() const; | 200 | const Kernel::KSharedMemory& GetFontSharedMem() const; |
| 203 | 201 | ||
| 204 | /// Gets the shared memory object for IRS services. | 202 | /// Gets the shared memory object for IRS services. |
| 205 | Kernel::SharedMemory& GetIrsSharedMem(); | 203 | Kernel::KSharedMemory& GetIrsSharedMem(); |
| 206 | 204 | ||
| 207 | /// Gets the shared memory object for IRS services. | 205 | /// Gets the shared memory object for IRS services. |
| 208 | const Kernel::SharedMemory& GetIrsSharedMem() const; | 206 | const Kernel::KSharedMemory& GetIrsSharedMem() const; |
| 209 | 207 | ||
| 210 | /// Gets the shared memory object for Time services. | 208 | /// Gets the shared memory object for Time services. |
| 211 | Kernel::SharedMemory& GetTimeSharedMem(); | 209 | Kernel::KSharedMemory& GetTimeSharedMem(); |
| 212 | 210 | ||
| 213 | /// Gets the shared memory object for Time services. | 211 | /// Gets the shared memory object for Time services. |
| 214 | const Kernel::SharedMemory& GetTimeSharedMem() const; | 212 | const Kernel::KSharedMemory& GetTimeSharedMem() const; |
| 215 | 213 | ||
| 216 | /// Suspend/unsuspend the OS. | 214 | /// Suspend/unsuspend the OS. |
| 217 | void Suspend(bool in_suspention); | 215 | void Suspend(bool in_suspention); |
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 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #pragma once | ||
| 9 | |||
| 10 | #include <array> | ||
| 11 | #include <bit> | ||
| 12 | #include <vector> | ||
| 13 | |||
| 14 | #include "common/alignment.h" | ||
| 15 | #include "common/assert.h" | ||
| 16 | #include "common/common_funcs.h" | ||
| 17 | #include "common/common_types.h" | ||
| 18 | #include "core/hle/kernel/memory/memory_types.h" | ||
| 19 | |||
| 20 | namespace Kernel::Memory { | ||
| 21 | |||
| 22 | class PageHeap final : NonCopyable { | ||
| 23 | public: | ||
| 24 | static constexpr s32 GetAlignedBlockIndex(std::size_t num_pages, std::size_t align_pages) { | ||
| 25 | const auto target_pages{std::max(num_pages, align_pages)}; | ||
| 26 | for (std::size_t i = 0; i < NumMemoryBlockPageShifts; i++) { | ||
| 27 | if (target_pages <= | ||
| 28 | (static_cast<std::size_t>(1) << MemoryBlockPageShifts[i]) / PageSize) { | ||
| 29 | return static_cast<s32>(i); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | return -1; | ||
| 33 | } | ||
| 34 | |||
| 35 | static constexpr s32 GetBlockIndex(std::size_t num_pages) { | ||
| 36 | for (s32 i{static_cast<s32>(NumMemoryBlockPageShifts) - 1}; i >= 0; i--) { | ||
| 37 | if (num_pages >= (static_cast<std::size_t>(1) << MemoryBlockPageShifts[i]) / PageSize) { | ||
| 38 | return i; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | return -1; | ||
| 42 | } | ||
| 43 | |||
| 44 | static constexpr std::size_t GetBlockSize(std::size_t index) { | ||
| 45 | return static_cast<std::size_t>(1) << MemoryBlockPageShifts[index]; | ||
| 46 | } | ||
| 47 | |||
| 48 | static constexpr std::size_t GetBlockNumPages(std::size_t index) { | ||
| 49 | return GetBlockSize(index) / PageSize; | ||
| 50 | } | ||
| 51 | |||
| 52 | private: | ||
| 53 | static constexpr std::size_t NumMemoryBlockPageShifts{7}; | ||
| 54 | static constexpr std::array<std::size_t, NumMemoryBlockPageShifts> MemoryBlockPageShifts{ | ||
| 55 | 0xC, 0x10, 0x15, 0x16, 0x19, 0x1D, 0x1E, | ||
| 56 | }; | ||
| 57 | |||
| 58 | class Block final : NonCopyable { | ||
| 59 | private: | ||
| 60 | class Bitmap final : NonCopyable { | ||
| 61 | public: | ||
| 62 | static constexpr std::size_t MaxDepth{4}; | ||
| 63 | |||
| 64 | private: | ||
| 65 | std::array<u64*, MaxDepth> bit_storages{}; | ||
| 66 | std::size_t num_bits{}; | ||
| 67 | std::size_t used_depths{}; | ||
| 68 | |||
| 69 | public: | ||
| 70 | constexpr Bitmap() = default; | ||
| 71 | |||
| 72 | constexpr std::size_t GetNumBits() const { | ||
| 73 | return num_bits; | ||
| 74 | } | ||
| 75 | constexpr s32 GetHighestDepthIndex() const { | ||
| 76 | return static_cast<s32>(used_depths) - 1; | ||
| 77 | } | ||
| 78 | |||
| 79 | constexpr u64* Initialize(u64* storage, std::size_t size) { | ||
| 80 | //* Initially, everything is un-set | ||
| 81 | num_bits = 0; | ||
| 82 | |||
| 83 | // Calculate the needed bitmap depth | ||
| 84 | used_depths = static_cast<std::size_t>(GetRequiredDepth(size)); | ||
| 85 | ASSERT(used_depths <= MaxDepth); | ||
| 86 | |||
| 87 | // Set the bitmap pointers | ||
| 88 | for (s32 depth{GetHighestDepthIndex()}; depth >= 0; depth--) { | ||
| 89 | bit_storages[depth] = storage; | ||
| 90 | size = Common::AlignUp(size, 64) / 64; | ||
| 91 | storage += size; | ||
| 92 | } | ||
| 93 | |||
| 94 | return storage; | ||
| 95 | } | ||
| 96 | |||
| 97 | s64 FindFreeBlock() const { | ||
| 98 | uintptr_t offset{}; | ||
| 99 | s32 depth{}; | ||
| 100 | |||
| 101 | do { | ||
| 102 | const u64 v{bit_storages[depth][offset]}; | ||
| 103 | if (v == 0) { | ||
| 104 | // Non-zero depth indicates that a previous level had a free block | ||
| 105 | ASSERT(depth == 0); | ||
| 106 | return -1; | ||
| 107 | } | ||
| 108 | offset = offset * 64 + static_cast<u32>(std::countr_zero(v)); | ||
| 109 | ++depth; | ||
| 110 | } while (depth < static_cast<s32>(used_depths)); | ||
| 111 | |||
| 112 | return static_cast<s64>(offset); | ||
| 113 | } | ||
| 114 | |||
| 115 | constexpr void SetBit(std::size_t offset) { | ||
| 116 | SetBit(GetHighestDepthIndex(), offset); | ||
| 117 | num_bits++; | ||
| 118 | } | ||
| 119 | |||
| 120 | constexpr void ClearBit(std::size_t offset) { | ||
| 121 | ClearBit(GetHighestDepthIndex(), offset); | ||
| 122 | num_bits--; | ||
| 123 | } | ||
| 124 | |||
| 125 | constexpr bool ClearRange(std::size_t offset, std::size_t count) { | ||
| 126 | const s32 depth{GetHighestDepthIndex()}; | ||
| 127 | const auto bit_ind{offset / 64}; | ||
| 128 | u64* bits{bit_storages[depth]}; | ||
| 129 | if (count < 64) { | ||
| 130 | const auto shift{offset % 64}; | ||
| 131 | ASSERT(shift + count <= 64); | ||
| 132 | // Check that all the bits are set | ||
| 133 | const u64 mask{((1ULL << count) - 1) << shift}; | ||
| 134 | u64 v{bits[bit_ind]}; | ||
| 135 | if ((v & mask) != mask) { | ||
| 136 | return false; | ||
| 137 | } | ||
| 138 | |||
| 139 | // Clear the bits | ||
| 140 | v &= ~mask; | ||
| 141 | bits[bit_ind] = v; | ||
| 142 | if (v == 0) { | ||
| 143 | ClearBit(depth - 1, bit_ind); | ||
| 144 | } | ||
| 145 | } else { | ||
| 146 | ASSERT(offset % 64 == 0); | ||
| 147 | ASSERT(count % 64 == 0); | ||
| 148 | // Check that all the bits are set | ||
| 149 | std::size_t remaining{count}; | ||
| 150 | std::size_t i = 0; | ||
| 151 | do { | ||
| 152 | if (bits[bit_ind + i++] != ~u64(0)) { | ||
| 153 | return false; | ||
| 154 | } | ||
| 155 | remaining -= 64; | ||
| 156 | } while (remaining > 0); | ||
| 157 | |||
| 158 | // Clear the bits | ||
| 159 | remaining = count; | ||
| 160 | i = 0; | ||
| 161 | do { | ||
| 162 | bits[bit_ind + i] = 0; | ||
| 163 | ClearBit(depth - 1, bit_ind + i); | ||
| 164 | i++; | ||
| 165 | remaining -= 64; | ||
| 166 | } while (remaining > 0); | ||
| 167 | } | ||
| 168 | |||
| 169 | num_bits -= count; | ||
| 170 | return true; | ||
| 171 | } | ||
| 172 | |||
| 173 | private: | ||
| 174 | constexpr void SetBit(s32 depth, std::size_t offset) { | ||
| 175 | while (depth >= 0) { | ||
| 176 | const auto ind{offset / 64}; | ||
| 177 | const auto which{offset % 64}; | ||
| 178 | const u64 mask{1ULL << which}; | ||
| 179 | |||
| 180 | u64* bit{std::addressof(bit_storages[depth][ind])}; | ||
| 181 | const u64 v{*bit}; | ||
| 182 | ASSERT((v & mask) == 0); | ||
| 183 | *bit = v | mask; | ||
| 184 | if (v) { | ||
| 185 | break; | ||
| 186 | } | ||
| 187 | offset = ind; | ||
| 188 | depth--; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | constexpr void ClearBit(s32 depth, std::size_t offset) { | ||
| 193 | while (depth >= 0) { | ||
| 194 | const auto ind{offset / 64}; | ||
| 195 | const auto which{offset % 64}; | ||
| 196 | const u64 mask{1ULL << which}; | ||
| 197 | |||
| 198 | u64* bit{std::addressof(bit_storages[depth][ind])}; | ||
| 199 | u64 v{*bit}; | ||
| 200 | ASSERT((v & mask) != 0); | ||
| 201 | v &= ~mask; | ||
| 202 | *bit = v; | ||
| 203 | if (v) { | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | offset = ind; | ||
| 207 | depth--; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | private: | ||
| 212 | static constexpr s32 GetRequiredDepth(std::size_t region_size) { | ||
| 213 | s32 depth = 0; | ||
| 214 | while (true) { | ||
| 215 | region_size /= 64; | ||
| 216 | depth++; | ||
| 217 | if (region_size == 0) { | ||
| 218 | return depth; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | public: | ||
| 224 | static constexpr std::size_t CalculateMetadataOverheadSize(std::size_t region_size) { | ||
| 225 | std::size_t overhead_bits = 0; | ||
| 226 | for (s32 depth{GetRequiredDepth(region_size) - 1}; depth >= 0; depth--) { | ||
| 227 | region_size = Common::AlignUp(region_size, 64) / 64; | ||
| 228 | overhead_bits += region_size; | ||
| 229 | } | ||
| 230 | return overhead_bits * sizeof(u64); | ||
| 231 | } | ||
| 232 | }; | ||
| 233 | |||
| 234 | private: | ||
| 235 | Bitmap bitmap; | ||
| 236 | VAddr heap_address{}; | ||
| 237 | uintptr_t end_offset{}; | ||
| 238 | std::size_t block_shift{}; | ||
| 239 | std::size_t next_block_shift{}; | ||
| 240 | |||
| 241 | public: | ||
| 242 | constexpr Block() = default; | ||
| 243 | |||
| 244 | constexpr std::size_t GetShift() const { | ||
| 245 | return block_shift; | ||
| 246 | } | ||
| 247 | constexpr std::size_t GetNextShift() const { | ||
| 248 | return next_block_shift; | ||
| 249 | } | ||
| 250 | constexpr std::size_t GetSize() const { | ||
| 251 | return static_cast<std::size_t>(1) << GetShift(); | ||
| 252 | } | ||
| 253 | constexpr std::size_t GetNumPages() const { | ||
| 254 | return GetSize() / PageSize; | ||
| 255 | } | ||
| 256 | constexpr std::size_t GetNumFreeBlocks() const { | ||
| 257 | return bitmap.GetNumBits(); | ||
| 258 | } | ||
| 259 | constexpr std::size_t GetNumFreePages() const { | ||
| 260 | return GetNumFreeBlocks() * GetNumPages(); | ||
| 261 | } | ||
| 262 | |||
| 263 | constexpr u64* Initialize(VAddr addr, std::size_t size, std::size_t bs, std::size_t nbs, | ||
| 264 | u64* bit_storage) { | ||
| 265 | // Set shifts | ||
| 266 | block_shift = bs; | ||
| 267 | next_block_shift = nbs; | ||
| 268 | |||
| 269 | // Align up the address | ||
| 270 | VAddr end{addr + size}; | ||
| 271 | const auto align{(next_block_shift != 0) ? (1ULL << next_block_shift) | ||
| 272 | : (1ULL << block_shift)}; | ||
| 273 | addr = Common::AlignDown((addr), align); | ||
| 274 | end = Common::AlignUp((end), align); | ||
| 275 | |||
| 276 | heap_address = addr; | ||
| 277 | end_offset = (end - addr) / (1ULL << block_shift); | ||
| 278 | return bitmap.Initialize(bit_storage, end_offset); | ||
| 279 | } | ||
| 280 | |||
| 281 | constexpr VAddr PushBlock(VAddr address) { | ||
| 282 | // Set the bit for the free block | ||
| 283 | std::size_t offset{(address - heap_address) >> GetShift()}; | ||
| 284 | bitmap.SetBit(offset); | ||
| 285 | |||
| 286 | // If we have a next shift, try to clear the blocks below and return the address | ||
| 287 | if (GetNextShift()) { | ||
| 288 | const auto diff{1ULL << (GetNextShift() - GetShift())}; | ||
| 289 | offset = Common::AlignDown(offset, diff); | ||
| 290 | if (bitmap.ClearRange(offset, diff)) { | ||
| 291 | return heap_address + (offset << GetShift()); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | // We couldn't coalesce, or we're already as big as possible | ||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | VAddr PopBlock() { | ||
| 300 | // Find a free block | ||
| 301 | const s64 soffset{bitmap.FindFreeBlock()}; | ||
| 302 | if (soffset < 0) { | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | const auto offset{static_cast<std::size_t>(soffset)}; | ||
| 306 | |||
| 307 | // Update our tracking and return it | ||
| 308 | bitmap.ClearBit(offset); | ||
| 309 | return heap_address + (offset << GetShift()); | ||
| 310 | } | ||
| 311 | |||
| 312 | public: | ||
| 313 | static constexpr std::size_t CalculateMetadataOverheadSize(std::size_t region_size, | ||
| 314 | std::size_t cur_block_shift, | ||
| 315 | std::size_t next_block_shift) { | ||
| 316 | const auto cur_block_size{(1ULL << cur_block_shift)}; | ||
| 317 | const auto next_block_size{(1ULL << next_block_shift)}; | ||
| 318 | const auto align{(next_block_shift != 0) ? next_block_size : cur_block_size}; | ||
| 319 | return Bitmap::CalculateMetadataOverheadSize( | ||
| 320 | (align * 2 + Common::AlignUp(region_size, align)) / cur_block_size); | ||
| 321 | } | ||
| 322 | }; | ||
| 323 | |||
| 324 | public: | ||
| 325 | PageHeap() = default; | ||
| 326 | |||
| 327 | constexpr VAddr GetAddress() const { | ||
| 328 | return heap_address; | ||
| 329 | } | ||
| 330 | constexpr std::size_t GetSize() const { | ||
| 331 | return heap_size; | ||
| 332 | } | ||
| 333 | constexpr VAddr GetEndAddress() const { | ||
| 334 | return GetAddress() + GetSize(); | ||
| 335 | } | ||
| 336 | constexpr std::size_t GetPageOffset(VAddr block) const { | ||
| 337 | return (block - GetAddress()) / PageSize; | ||
| 338 | } | ||
| 339 | |||
| 340 | void Initialize(VAddr heap_address, std::size_t heap_size, std::size_t metadata_size); | ||
| 341 | VAddr AllocateBlock(s32 index); | ||
| 342 | void Free(VAddr addr, std::size_t num_pages); | ||
| 343 | |||
| 344 | void UpdateUsedSize() { | ||
| 345 | used_size = heap_size - (GetNumFreePages() * PageSize); | ||
| 346 | } | ||
| 347 | |||
| 348 | static std::size_t CalculateMetadataOverheadSize(std::size_t region_size); | ||
| 349 | |||
| 350 | private: | ||
| 351 | constexpr std::size_t GetNumFreePages() const { | ||
| 352 | std::size_t num_free{}; | ||
| 353 | |||
| 354 | for (const auto& block : blocks) { | ||
| 355 | num_free += block.GetNumFreePages(); | ||
| 356 | } | ||
| 357 | |||
| 358 | return num_free; | ||
| 359 | } | ||
| 360 | |||
| 361 | void FreeBlock(VAddr block, s32 index); | ||
| 362 | |||
| 363 | VAddr heap_address{}; | ||
| 364 | std::size_t heap_size{}; | ||
| 365 | std::size_t used_size{}; | ||
| 366 | std::array<Block, NumMemoryBlockPageShifts> blocks{}; | ||
| 367 | std::vector<u64> metadata; | ||
| 368 | }; | ||
| 369 | |||
| 370 | } // namespace Kernel::Memory | ||
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 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | namespace Kernel::Memory::SystemControl { | ||
| 10 | |||
| 11 | u64 GenerateRandomRange(u64 min, u64 max); | ||
| 12 | |||
| 13 | } // namespace Kernel::Memory::SystemControl | ||
diff --git a/src/core/hle/kernel/memory/memory_types.h b/src/core/hle/kernel/memory_types.h index a75bf77c0..d458f0eca 100644 --- a/src/core/hle/kernel/memory/memory_types.h +++ b/src/core/hle/kernel/memory_types.h | |||
| @@ -8,11 +8,11 @@ | |||
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | 10 | ||
| 11 | namespace Kernel::Memory { | 11 | namespace Kernel { |
| 12 | 12 | ||
| 13 | constexpr std::size_t PageBits{12}; | 13 | constexpr std::size_t PageBits{12}; |
| 14 | constexpr std::size_t PageSize{1 << PageBits}; | 14 | constexpr std::size_t PageSize{1 << PageBits}; |
| 15 | 15 | ||
| 16 | using Page = std::array<u8, PageSize>; | 16 | using Page = std::array<u8, PageSize>; |
| 17 | 17 | ||
| 18 | } // namespace Kernel::Memory | 18 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 47b3ac57b..73b85d6f9 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -14,14 +14,14 @@ | |||
| 14 | #include "core/device_memory.h" | 14 | #include "core/device_memory.h" |
| 15 | #include "core/file_sys/program_metadata.h" | 15 | #include "core/file_sys/program_metadata.h" |
| 16 | #include "core/hle/kernel/code_set.h" | 16 | #include "core/hle/kernel/code_set.h" |
| 17 | #include "core/hle/kernel/k_memory_block_manager.h" | ||
| 18 | #include "core/hle/kernel/k_page_table.h" | ||
| 17 | #include "core/hle/kernel/k_resource_limit.h" | 19 | #include "core/hle/kernel/k_resource_limit.h" |
| 18 | #include "core/hle/kernel/k_scheduler.h" | 20 | #include "core/hle/kernel/k_scheduler.h" |
| 19 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | 21 | #include "core/hle/kernel/k_scoped_resource_reservation.h" |
| 22 | #include "core/hle/kernel/k_slab_heap.h" | ||
| 20 | #include "core/hle/kernel/k_thread.h" | 23 | #include "core/hle/kernel/k_thread.h" |
| 21 | #include "core/hle/kernel/kernel.h" | 24 | #include "core/hle/kernel/kernel.h" |
| 22 | #include "core/hle/kernel/memory/memory_block_manager.h" | ||
| 23 | #include "core/hle/kernel/memory/page_table.h" | ||
| 24 | #include "core/hle/kernel/memory/slab_heap.h" | ||
| 25 | #include "core/hle/kernel/process.h" | 25 | #include "core/hle/kernel/process.h" |
| 26 | #include "core/hle/kernel/svc_results.h" | 26 | #include "core/hle/kernel/svc_results.h" |
| 27 | #include "core/hle/lock.h" | 27 | #include "core/hle/lock.h" |
| @@ -274,7 +274,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 274 | // Set initial resource limits | 274 | // Set initial resource limits |
| 275 | resource_limit->SetLimitValue( | 275 | resource_limit->SetLimitValue( |
| 276 | LimitableResource::PhysicalMemory, | 276 | LimitableResource::PhysicalMemory, |
| 277 | kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application)); | 277 | kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); |
| 278 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | 278 | KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, |
| 279 | code_size + system_resource_size); | 279 | code_size + system_resource_size); |
| 280 | if (!memory_reservation.Succeeded()) { | 280 | if (!memory_reservation.Succeeded()) { |
| @@ -285,15 +285,15 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 285 | // Initialize proces address space | 285 | // Initialize proces address space |
| 286 | if (const ResultCode result{ | 286 | if (const ResultCode result{ |
| 287 | page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false, 0x8000000, | 287 | page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false, 0x8000000, |
| 288 | code_size, Memory::MemoryManager::Pool::Application)}; | 288 | code_size, KMemoryManager::Pool::Application)}; |
| 289 | result.IsError()) { | 289 | result.IsError()) { |
| 290 | return result; | 290 | return result; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | // Map process code region | 293 | // Map process code region |
| 294 | if (const ResultCode result{page_table->MapProcessCode( | 294 | if (const ResultCode result{page_table->MapProcessCode(page_table->GetCodeRegionStart(), |
| 295 | page_table->GetCodeRegionStart(), code_size / Memory::PageSize, | 295 | code_size / PageSize, KMemoryState::Code, |
| 296 | Memory::MemoryState::Code, Memory::MemoryPermission::None)}; | 296 | KMemoryPermission::None)}; |
| 297 | result.IsError()) { | 297 | result.IsError()) { |
| 298 | return result; | 298 | return result; |
| 299 | } | 299 | } |
| @@ -323,6 +323,11 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, | |||
| 323 | UNREACHABLE(); | 323 | UNREACHABLE(); |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | // Set initial resource limits | ||
| 327 | resource_limit->SetLimitValue( | ||
| 328 | LimitableResource::PhysicalMemory, | ||
| 329 | kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application)); | ||
| 330 | |||
| 326 | resource_limit->SetLimitValue(LimitableResource::Threads, 608); | 331 | resource_limit->SetLimitValue(LimitableResource::Threads, 608); |
| 327 | resource_limit->SetLimitValue(LimitableResource::Events, 700); | 332 | resource_limit->SetLimitValue(LimitableResource::Events, 700); |
| 328 | resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); | 333 | resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); |
| @@ -400,22 +405,22 @@ VAddr Process::CreateTLSRegion() { | |||
| 400 | return *tls_page_iter->ReserveSlot(); | 405 | return *tls_page_iter->ReserveSlot(); |
| 401 | } | 406 | } |
| 402 | 407 | ||
| 403 | Memory::Page* const tls_page_ptr{kernel.GetUserSlabHeapPages().Allocate()}; | 408 | Page* const tls_page_ptr{kernel.GetUserSlabHeapPages().Allocate()}; |
| 404 | ASSERT(tls_page_ptr); | 409 | ASSERT(tls_page_ptr); |
| 405 | 410 | ||
| 406 | const VAddr start{page_table->GetKernelMapRegionStart()}; | 411 | const VAddr start{page_table->GetKernelMapRegionStart()}; |
| 407 | const VAddr size{page_table->GetKernelMapRegionEnd() - start}; | 412 | const VAddr size{page_table->GetKernelMapRegionEnd() - start}; |
| 408 | const PAddr tls_map_addr{system.DeviceMemory().GetPhysicalAddr(tls_page_ptr)}; | 413 | const PAddr tls_map_addr{system.DeviceMemory().GetPhysicalAddr(tls_page_ptr)}; |
| 409 | const VAddr tls_page_addr{ | 414 | const VAddr tls_page_addr{page_table |
| 410 | page_table | 415 | ->AllocateAndMapMemory(1, PageSize, true, start, size / PageSize, |
| 411 | ->AllocateAndMapMemory(1, Memory::PageSize, true, start, size / Memory::PageSize, | 416 | KMemoryState::ThreadLocal, |
| 412 | Memory::MemoryState::ThreadLocal, | 417 | KMemoryPermission::ReadAndWrite, |
| 413 | Memory::MemoryPermission::ReadAndWrite, tls_map_addr) | 418 | tls_map_addr) |
| 414 | .ValueOr(0)}; | 419 | .ValueOr(0)}; |
| 415 | 420 | ||
| 416 | ASSERT(tls_page_addr); | 421 | ASSERT(tls_page_addr); |
| 417 | 422 | ||
| 418 | std::memset(tls_page_ptr, 0, Memory::PageSize); | 423 | std::memset(tls_page_ptr, 0, PageSize); |
| 419 | tls_pages.emplace_back(tls_page_addr); | 424 | tls_pages.emplace_back(tls_page_addr); |
| 420 | 425 | ||
| 421 | const auto reserve_result{tls_pages.back().ReserveSlot()}; | 426 | const auto reserve_result{tls_pages.back().ReserveSlot()}; |
| @@ -442,15 +447,15 @@ void Process::FreeTLSRegion(VAddr tls_address) { | |||
| 442 | void Process::LoadModule(CodeSet code_set, VAddr base_addr) { | 447 | void Process::LoadModule(CodeSet code_set, VAddr base_addr) { |
| 443 | std::lock_guard lock{HLE::g_hle_lock}; | 448 | std::lock_guard lock{HLE::g_hle_lock}; |
| 444 | const auto ReprotectSegment = [&](const CodeSet::Segment& segment, | 449 | const auto ReprotectSegment = [&](const CodeSet::Segment& segment, |
| 445 | Memory::MemoryPermission permission) { | 450 | KMemoryPermission permission) { |
| 446 | page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission); | 451 | page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission); |
| 447 | }; | 452 | }; |
| 448 | 453 | ||
| 449 | system.Memory().WriteBlock(*this, base_addr, code_set.memory.data(), code_set.memory.size()); | 454 | system.Memory().WriteBlock(*this, base_addr, code_set.memory.data(), code_set.memory.size()); |
| 450 | 455 | ||
| 451 | ReprotectSegment(code_set.CodeSegment(), Memory::MemoryPermission::ReadAndExecute); | 456 | ReprotectSegment(code_set.CodeSegment(), KMemoryPermission::ReadAndExecute); |
| 452 | ReprotectSegment(code_set.RODataSegment(), Memory::MemoryPermission::Read); | 457 | ReprotectSegment(code_set.RODataSegment(), KMemoryPermission::Read); |
| 453 | ReprotectSegment(code_set.DataSegment(), Memory::MemoryPermission::ReadAndWrite); | 458 | ReprotectSegment(code_set.DataSegment(), KMemoryPermission::ReadAndWrite); |
| 454 | } | 459 | } |
| 455 | 460 | ||
| 456 | bool Process::IsSignaled() const { | 461 | bool Process::IsSignaled() const { |
| @@ -459,9 +464,9 @@ bool Process::IsSignaled() const { | |||
| 459 | } | 464 | } |
| 460 | 465 | ||
| 461 | Process::Process(Core::System& system) | 466 | Process::Process(Core::System& system) |
| 462 | : KSynchronizationObject{system.Kernel()}, | 467 | : KSynchronizationObject{system.Kernel()}, page_table{std::make_unique<KPageTable>(system)}, |
| 463 | page_table{std::make_unique<Memory::PageTable>(system)}, handle_table{system.Kernel()}, | 468 | handle_table{system.Kernel()}, address_arbiter{system}, condition_var{system}, |
| 464 | address_arbiter{system}, condition_var{system}, state_lock{system.Kernel()}, system{system} {} | 469 | state_lock{system.Kernel()}, system{system} {} |
| 465 | 470 | ||
| 466 | Process::~Process() = default; | 471 | Process::~Process() = default; |
| 467 | 472 | ||
| @@ -479,16 +484,15 @@ ResultCode Process::AllocateMainThreadStack(std::size_t stack_size) { | |||
| 479 | ASSERT(stack_size); | 484 | ASSERT(stack_size); |
| 480 | 485 | ||
| 481 | // The kernel always ensures that the given stack size is page aligned. | 486 | // The kernel always ensures that the given stack size is page aligned. |
| 482 | main_thread_stack_size = Common::AlignUp(stack_size, Memory::PageSize); | 487 | main_thread_stack_size = Common::AlignUp(stack_size, PageSize); |
| 483 | 488 | ||
| 484 | const VAddr start{page_table->GetStackRegionStart()}; | 489 | const VAddr start{page_table->GetStackRegionStart()}; |
| 485 | const std::size_t size{page_table->GetStackRegionEnd() - start}; | 490 | const std::size_t size{page_table->GetStackRegionEnd() - start}; |
| 486 | 491 | ||
| 487 | CASCADE_RESULT(main_thread_stack_top, | 492 | CASCADE_RESULT(main_thread_stack_top, |
| 488 | page_table->AllocateAndMapMemory( | 493 | page_table->AllocateAndMapMemory( |
| 489 | main_thread_stack_size / Memory::PageSize, Memory::PageSize, false, start, | 494 | main_thread_stack_size / PageSize, PageSize, false, start, size / PageSize, |
| 490 | size / Memory::PageSize, Memory::MemoryState::Stack, | 495 | KMemoryState::Stack, KMemoryPermission::ReadAndWrite)); |
| 491 | Memory::MemoryPermission::ReadAndWrite)); | ||
| 492 | 496 | ||
| 493 | main_thread_stack_top += main_thread_stack_size; | 497 | main_thread_stack_top += main_thread_stack_size; |
| 494 | 498 | ||
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 320b0f347..45eefb90e 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -29,16 +29,13 @@ class ProgramMetadata; | |||
| 29 | namespace Kernel { | 29 | namespace Kernel { |
| 30 | 30 | ||
| 31 | class KernelCore; | 31 | class KernelCore; |
| 32 | class KPageTable; | ||
| 32 | class KResourceLimit; | 33 | class KResourceLimit; |
| 33 | class KThread; | 34 | class KThread; |
| 34 | class TLSPage; | 35 | class TLSPage; |
| 35 | 36 | ||
| 36 | struct CodeSet; | 37 | struct CodeSet; |
| 37 | 38 | ||
| 38 | namespace Memory { | ||
| 39 | class PageTable; | ||
| 40 | } | ||
| 41 | |||
| 42 | enum class MemoryRegion : u16 { | 39 | enum class MemoryRegion : u16 { |
| 43 | APPLICATION = 1, | 40 | APPLICATION = 1, |
| 44 | SYSTEM = 2, | 41 | SYSTEM = 2, |
| @@ -104,12 +101,12 @@ public: | |||
| 104 | } | 101 | } |
| 105 | 102 | ||
| 106 | /// Gets a reference to the process' page table. | 103 | /// Gets a reference to the process' page table. |
| 107 | Memory::PageTable& PageTable() { | 104 | KPageTable& PageTable() { |
| 108 | return *page_table; | 105 | return *page_table; |
| 109 | } | 106 | } |
| 110 | 107 | ||
| 111 | /// Gets const a reference to the process' page table. | 108 | /// Gets const a reference to the process' page table. |
| 112 | const Memory::PageTable& PageTable() const { | 109 | const KPageTable& PageTable() const { |
| 113 | return *page_table; | 110 | return *page_table; |
| 114 | } | 111 | } |
| 115 | 112 | ||
| @@ -385,7 +382,7 @@ private: | |||
| 385 | ResultCode AllocateMainThreadStack(std::size_t stack_size); | 382 | ResultCode AllocateMainThreadStack(std::size_t stack_size); |
| 386 | 383 | ||
| 387 | /// Memory manager for this process | 384 | /// Memory manager for this process |
| 388 | std::unique_ptr<Memory::PageTable> page_table; | 385 | std::unique_ptr<KPageTable> page_table; |
| 389 | 386 | ||
| 390 | /// Current status of the process | 387 | /// Current status of the process |
| 391 | ProcessStatus status{}; | 388 | ProcessStatus status{}; |
diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp index 7c567049e..3fc326eab 100644 --- a/src/core/hle/kernel/process_capability.cpp +++ b/src/core/hle/kernel/process_capability.cpp | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | #include "common/bit_util.h" | 7 | #include "common/bit_util.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/hle/kernel/handle_table.h" | 9 | #include "core/hle/kernel/handle_table.h" |
| 10 | #include "core/hle/kernel/memory/page_table.h" | 10 | #include "core/hle/kernel/k_page_table.h" |
| 11 | #include "core/hle/kernel/process_capability.h" | 11 | #include "core/hle/kernel/process_capability.h" |
| 12 | #include "core/hle/kernel/svc_results.h" | 12 | #include "core/hle/kernel/svc_results.h" |
| 13 | 13 | ||
| @@ -69,7 +69,7 @@ u32 GetFlagBitOffset(CapabilityType type) { | |||
| 69 | 69 | ||
| 70 | ResultCode ProcessCapabilities::InitializeForKernelProcess(const u32* capabilities, | 70 | ResultCode ProcessCapabilities::InitializeForKernelProcess(const u32* capabilities, |
| 71 | std::size_t num_capabilities, | 71 | std::size_t num_capabilities, |
| 72 | Memory::PageTable& page_table) { | 72 | KPageTable& page_table) { |
| 73 | Clear(); | 73 | Clear(); |
| 74 | 74 | ||
| 75 | // Allow all cores and priorities. | 75 | // Allow all cores and priorities. |
| @@ -82,7 +82,7 @@ ResultCode ProcessCapabilities::InitializeForKernelProcess(const u32* capabiliti | |||
| 82 | 82 | ||
| 83 | ResultCode ProcessCapabilities::InitializeForUserProcess(const u32* capabilities, | 83 | ResultCode ProcessCapabilities::InitializeForUserProcess(const u32* capabilities, |
| 84 | std::size_t num_capabilities, | 84 | std::size_t num_capabilities, |
| 85 | Memory::PageTable& page_table) { | 85 | KPageTable& page_table) { |
| 86 | Clear(); | 86 | Clear(); |
| 87 | 87 | ||
| 88 | return ParseCapabilities(capabilities, num_capabilities, page_table); | 88 | return ParseCapabilities(capabilities, num_capabilities, page_table); |
| @@ -108,7 +108,7 @@ void ProcessCapabilities::InitializeForMetadatalessProcess() { | |||
| 108 | 108 | ||
| 109 | ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities, | 109 | ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities, |
| 110 | std::size_t num_capabilities, | 110 | std::size_t num_capabilities, |
| 111 | Memory::PageTable& page_table) { | 111 | KPageTable& page_table) { |
| 112 | u32 set_flags = 0; | 112 | u32 set_flags = 0; |
| 113 | u32 set_svc_bits = 0; | 113 | u32 set_svc_bits = 0; |
| 114 | 114 | ||
| @@ -155,7 +155,7 @@ ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities, | |||
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, | 157 | ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, |
| 158 | u32 flag, Memory::PageTable& page_table) { | 158 | u32 flag, KPageTable& page_table) { |
| 159 | const auto type = GetCapabilityType(flag); | 159 | const auto type = GetCapabilityType(flag); |
| 160 | 160 | ||
| 161 | if (type == CapabilityType::Unset) { | 161 | if (type == CapabilityType::Unset) { |
| @@ -293,12 +293,12 @@ ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags) | |||
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | ResultCode ProcessCapabilities::HandleMapPhysicalFlags(u32 flags, u32 size_flags, | 295 | ResultCode ProcessCapabilities::HandleMapPhysicalFlags(u32 flags, u32 size_flags, |
| 296 | Memory::PageTable& page_table) { | 296 | KPageTable& page_table) { |
| 297 | // TODO(Lioncache): Implement once the memory manager can handle this. | 297 | // TODO(Lioncache): Implement once the memory manager can handle this. |
| 298 | return RESULT_SUCCESS; | 298 | return RESULT_SUCCESS; |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 301 | ResultCode ProcessCapabilities::HandleMapIOFlags(u32 flags, Memory::PageTable& page_table) { | 301 | ResultCode ProcessCapabilities::HandleMapIOFlags(u32 flags, KPageTable& page_table) { |
| 302 | // TODO(Lioncache): Implement once the memory manager can handle this. | 302 | // TODO(Lioncache): Implement once the memory manager can handle this. |
| 303 | return RESULT_SUCCESS; | 303 | return RESULT_SUCCESS; |
| 304 | } | 304 | } |
diff --git a/src/core/hle/kernel/process_capability.h b/src/core/hle/kernel/process_capability.h index ea9d12c16..73ad197fa 100644 --- a/src/core/hle/kernel/process_capability.h +++ b/src/core/hle/kernel/process_capability.h | |||
| @@ -12,9 +12,7 @@ union ResultCode; | |||
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | namespace Memory { | 15 | class KPageTable; |
| 16 | class PageTable; | ||
| 17 | } | ||
| 18 | 16 | ||
| 19 | /// The possible types of programs that may be indicated | 17 | /// The possible types of programs that may be indicated |
| 20 | /// by the program type capability descriptor. | 18 | /// by the program type capability descriptor. |
| @@ -90,7 +88,7 @@ public: | |||
| 90 | /// otherwise, an error code upon failure. | 88 | /// otherwise, an error code upon failure. |
| 91 | /// | 89 | /// |
| 92 | ResultCode InitializeForKernelProcess(const u32* capabilities, std::size_t num_capabilities, | 90 | ResultCode InitializeForKernelProcess(const u32* capabilities, std::size_t num_capabilities, |
| 93 | Memory::PageTable& page_table); | 91 | KPageTable& page_table); |
| 94 | 92 | ||
| 95 | /// Initializes this process capabilities instance for a userland process. | 93 | /// Initializes this process capabilities instance for a userland process. |
| 96 | /// | 94 | /// |
| @@ -103,7 +101,7 @@ public: | |||
| 103 | /// otherwise, an error code upon failure. | 101 | /// otherwise, an error code upon failure. |
| 104 | /// | 102 | /// |
| 105 | ResultCode InitializeForUserProcess(const u32* capabilities, std::size_t num_capabilities, | 103 | ResultCode InitializeForUserProcess(const u32* capabilities, std::size_t num_capabilities, |
| 106 | Memory::PageTable& page_table); | 104 | KPageTable& page_table); |
| 107 | 105 | ||
| 108 | /// Initializes this process capabilities instance for a process that does not | 106 | /// Initializes this process capabilities instance for a process that does not |
| 109 | /// have any metadata to parse. | 107 | /// have any metadata to parse. |
| @@ -189,7 +187,7 @@ private: | |||
| 189 | /// @return RESULT_SUCCESS if no errors occur, otherwise an error code. | 187 | /// @return RESULT_SUCCESS if no errors occur, otherwise an error code. |
| 190 | /// | 188 | /// |
| 191 | ResultCode ParseCapabilities(const u32* capabilities, std::size_t num_capabilities, | 189 | ResultCode ParseCapabilities(const u32* capabilities, std::size_t num_capabilities, |
| 192 | Memory::PageTable& page_table); | 190 | KPageTable& page_table); |
| 193 | 191 | ||
| 194 | /// Attempts to parse a capability descriptor that is only represented by a | 192 | /// Attempts to parse a capability descriptor that is only represented by a |
| 195 | /// single flag set. | 193 | /// single flag set. |
| @@ -204,7 +202,7 @@ private: | |||
| 204 | /// @return RESULT_SUCCESS if no errors occurred, otherwise an error code. | 202 | /// @return RESULT_SUCCESS if no errors occurred, otherwise an error code. |
| 205 | /// | 203 | /// |
| 206 | ResultCode ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, u32 flag, | 204 | ResultCode ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, u32 flag, |
| 207 | Memory::PageTable& page_table); | 205 | KPageTable& page_table); |
| 208 | 206 | ||
| 209 | /// Clears the internal state of this process capability instance. Necessary, | 207 | /// Clears the internal state of this process capability instance. Necessary, |
| 210 | /// to have a sane starting point due to us allowing running executables without | 208 | /// to have a sane starting point due to us allowing running executables without |
| @@ -228,10 +226,10 @@ private: | |||
| 228 | ResultCode HandleSyscallFlags(u32& set_svc_bits, u32 flags); | 226 | ResultCode HandleSyscallFlags(u32& set_svc_bits, u32 flags); |
| 229 | 227 | ||
| 230 | /// Handles flags related to mapping physical memory pages. | 228 | /// Handles flags related to mapping physical memory pages. |
| 231 | ResultCode HandleMapPhysicalFlags(u32 flags, u32 size_flags, Memory::PageTable& page_table); | 229 | ResultCode HandleMapPhysicalFlags(u32 flags, u32 size_flags, KPageTable& page_table); |
| 232 | 230 | ||
| 233 | /// Handles flags related to mapping IO pages. | 231 | /// Handles flags related to mapping IO pages. |
| 234 | ResultCode HandleMapIOFlags(u32 flags, Memory::PageTable& page_table); | 232 | ResultCode HandleMapIOFlags(u32 flags, KPageTable& page_table); |
| 235 | 233 | ||
| 236 | /// Handles flags related to the interrupt capability flags. | 234 | /// Handles flags related to the interrupt capability flags. |
| 237 | ResultCode HandleInterruptFlags(u32 flags); | 235 | ResultCode HandleInterruptFlags(u32 flags); |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 31d899e06..cc8fa6576 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -27,21 +27,21 @@ | |||
| 27 | #include "core/hle/kernel/k_address_arbiter.h" | 27 | #include "core/hle/kernel/k_address_arbiter.h" |
| 28 | #include "core/hle/kernel/k_condition_variable.h" | 28 | #include "core/hle/kernel/k_condition_variable.h" |
| 29 | #include "core/hle/kernel/k_event.h" | 29 | #include "core/hle/kernel/k_event.h" |
| 30 | #include "core/hle/kernel/k_memory_block.h" | ||
| 31 | #include "core/hle/kernel/k_memory_layout.h" | ||
| 32 | #include "core/hle/kernel/k_page_table.h" | ||
| 30 | #include "core/hle/kernel/k_readable_event.h" | 33 | #include "core/hle/kernel/k_readable_event.h" |
| 31 | #include "core/hle/kernel/k_resource_limit.h" | 34 | #include "core/hle/kernel/k_resource_limit.h" |
| 32 | #include "core/hle/kernel/k_scheduler.h" | 35 | #include "core/hle/kernel/k_scheduler.h" |
| 33 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | 36 | #include "core/hle/kernel/k_scoped_resource_reservation.h" |
| 34 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | 37 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" |
| 38 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 35 | #include "core/hle/kernel/k_synchronization_object.h" | 39 | #include "core/hle/kernel/k_synchronization_object.h" |
| 36 | #include "core/hle/kernel/k_thread.h" | 40 | #include "core/hle/kernel/k_thread.h" |
| 37 | #include "core/hle/kernel/k_writable_event.h" | 41 | #include "core/hle/kernel/k_writable_event.h" |
| 38 | #include "core/hle/kernel/kernel.h" | 42 | #include "core/hle/kernel/kernel.h" |
| 39 | #include "core/hle/kernel/memory/memory_block.h" | ||
| 40 | #include "core/hle/kernel/memory/memory_layout.h" | ||
| 41 | #include "core/hle/kernel/memory/page_table.h" | ||
| 42 | #include "core/hle/kernel/physical_core.h" | 43 | #include "core/hle/kernel/physical_core.h" |
| 43 | #include "core/hle/kernel/process.h" | 44 | #include "core/hle/kernel/process.h" |
| 44 | #include "core/hle/kernel/shared_memory.h" | ||
| 45 | #include "core/hle/kernel/svc.h" | 45 | #include "core/hle/kernel/svc.h" |
| 46 | #include "core/hle/kernel/svc_results.h" | 46 | #include "core/hle/kernel/svc_results.h" |
| 47 | #include "core/hle/kernel/svc_types.h" | 47 | #include "core/hle/kernel/svc_types.h" |
| @@ -67,8 +67,8 @@ constexpr bool IsValidAddressRange(VAddr address, u64 size) { | |||
| 67 | // Helper function that performs the common sanity checks for svcMapMemory | 67 | // Helper function that performs the common sanity checks for svcMapMemory |
| 68 | // and svcUnmapMemory. This is doable, as both functions perform their sanitizing | 68 | // and svcUnmapMemory. This is doable, as both functions perform their sanitizing |
| 69 | // in the same order. | 69 | // in the same order. |
| 70 | ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr dst_addr, | 70 | ResultCode MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, VAddr src_addr, |
| 71 | VAddr src_addr, u64 size) { | 71 | u64 size) { |
| 72 | if (!Common::Is4KBAligned(dst_addr)) { | 72 | if (!Common::Is4KBAligned(dst_addr)) { |
| 73 | LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr); | 73 | LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr); |
| 74 | return ResultInvalidAddress; | 74 | return ResultInvalidAddress; |
| @@ -230,9 +230,9 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si | |||
| 230 | return ResultInvalidCurrentMemory; | 230 | return ResultInvalidCurrentMemory; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | const auto attributes{static_cast<Memory::MemoryAttribute>(mask | attribute)}; | 233 | const auto attributes{static_cast<MemoryAttribute>(mask | attribute)}; |
| 234 | if (attributes != static_cast<Memory::MemoryAttribute>(mask) || | 234 | if (attributes != static_cast<MemoryAttribute>(mask) || |
| 235 | (attributes | Memory::MemoryAttribute::Uncached) != Memory::MemoryAttribute::Uncached) { | 235 | (attributes | MemoryAttribute::Uncached) != MemoryAttribute::Uncached) { |
| 236 | LOG_ERROR(Kernel_SVC, | 236 | LOG_ERROR(Kernel_SVC, |
| 237 | "Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}", | 237 | "Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}", |
| 238 | attribute, mask); | 238 | attribute, mask); |
| @@ -241,8 +241,8 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si | |||
| 241 | 241 | ||
| 242 | auto& page_table{system.Kernel().CurrentProcess()->PageTable()}; | 242 | auto& page_table{system.Kernel().CurrentProcess()->PageTable()}; |
| 243 | 243 | ||
| 244 | return page_table.SetMemoryAttribute(address, size, static_cast<Memory::MemoryAttribute>(mask), | 244 | return page_table.SetMemoryAttribute(address, size, static_cast<KMemoryAttribute>(mask), |
| 245 | static_cast<Memory::MemoryAttribute>(attribute)); | 245 | static_cast<KMemoryAttribute>(attribute)); |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, | 248 | static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, |
| @@ -508,7 +508,7 @@ static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAdd | |||
| 508 | thread_handle, address, tag); | 508 | thread_handle, address, tag); |
| 509 | 509 | ||
| 510 | // Validate the input address. | 510 | // Validate the input address. |
| 511 | if (Memory::IsKernelAddress(address)) { | 511 | if (IsKernelAddress(address)) { |
| 512 | LOG_ERROR(Kernel_SVC, "Attempting to arbitrate a lock on a kernel address (address={:08X})", | 512 | LOG_ERROR(Kernel_SVC, "Attempting to arbitrate a lock on a kernel address (address={:08X})", |
| 513 | address); | 513 | address); |
| 514 | return ResultInvalidCurrentMemory; | 514 | return ResultInvalidCurrentMemory; |
| @@ -531,8 +531,7 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) { | |||
| 531 | LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); | 531 | LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); |
| 532 | 532 | ||
| 533 | // Validate the input address. | 533 | // Validate the input address. |
| 534 | 534 | if (IsKernelAddress(address)) { | |
| 535 | if (Memory::IsKernelAddress(address)) { | ||
| 536 | LOG_ERROR(Kernel_SVC, | 535 | LOG_ERROR(Kernel_SVC, |
| 537 | "Attempting to arbitrate an unlock on a kernel address (address={:08X})", | 536 | "Attempting to arbitrate an unlock on a kernel address (address={:08X})", |
| 538 | address); | 537 | address); |
| @@ -1232,9 +1231,8 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han | |||
| 1232 | return ResultInvalidCurrentMemory; | 1231 | return ResultInvalidCurrentMemory; |
| 1233 | } | 1232 | } |
| 1234 | 1233 | ||
| 1235 | const auto permission_type = static_cast<Memory::MemoryPermission>(permissions); | 1234 | const auto permission_type = static_cast<MemoryPermission>(permissions); |
| 1236 | if ((permission_type | Memory::MemoryPermission::Write) != | 1235 | if ((permission_type | MemoryPermission::Write) != MemoryPermission::ReadWrite) { |
| 1237 | Memory::MemoryPermission::ReadAndWrite) { | ||
| 1238 | LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}", | 1236 | LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}", |
| 1239 | permissions); | 1237 | permissions); |
| 1240 | return ResultInvalidMemoryPermissions; | 1238 | return ResultInvalidMemoryPermissions; |
| @@ -1267,14 +1265,15 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han | |||
| 1267 | return ResultInvalidMemoryRange; | 1265 | return ResultInvalidMemoryRange; |
| 1268 | } | 1266 | } |
| 1269 | 1267 | ||
| 1270 | auto shared_memory{current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle)}; | 1268 | auto shared_memory{current_process->GetHandleTable().Get<KSharedMemory>(shared_memory_handle)}; |
| 1271 | if (!shared_memory) { | 1269 | if (!shared_memory) { |
| 1272 | LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}", | 1270 | LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}", |
| 1273 | shared_memory_handle); | 1271 | shared_memory_handle); |
| 1274 | return ResultInvalidHandle; | 1272 | return ResultInvalidHandle; |
| 1275 | } | 1273 | } |
| 1276 | 1274 | ||
| 1277 | return shared_memory->Map(*current_process, addr, size, permission_type); | 1275 | return shared_memory->Map(*current_process, addr, size, |
| 1276 | static_cast<KMemoryPermission>(permission_type)); | ||
| 1278 | } | 1277 | } |
| 1279 | 1278 | ||
| 1280 | static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, | 1279 | static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, |
| @@ -1638,7 +1637,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address, | |||
| 1638 | cv_key, tag, timeout_ns); | 1637 | cv_key, tag, timeout_ns); |
| 1639 | 1638 | ||
| 1640 | // Validate input. | 1639 | // Validate input. |
| 1641 | if (Memory::IsKernelAddress(address)) { | 1640 | if (IsKernelAddress(address)) { |
| 1642 | LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address); | 1641 | LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address); |
| 1643 | return ResultInvalidCurrentMemory; | 1642 | return ResultInvalidCurrentMemory; |
| 1644 | } | 1643 | } |
| @@ -1720,7 +1719,7 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::Arbit | |||
| 1720 | address, arb_type, value, timeout_ns); | 1719 | address, arb_type, value, timeout_ns); |
| 1721 | 1720 | ||
| 1722 | // Validate input. | 1721 | // Validate input. |
| 1723 | if (Memory::IsKernelAddress(address)) { | 1722 | if (IsKernelAddress(address)) { |
| 1724 | LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address); | 1723 | LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address); |
| 1725 | return ResultInvalidCurrentMemory; | 1724 | return ResultInvalidCurrentMemory; |
| 1726 | } | 1725 | } |
| @@ -1765,7 +1764,7 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign | |||
| 1765 | address, signal_type, value, count); | 1764 | address, signal_type, value, count); |
| 1766 | 1765 | ||
| 1767 | // Validate input. | 1766 | // Validate input. |
| 1768 | if (Memory::IsKernelAddress(address)) { | 1767 | if (IsKernelAddress(address)) { |
| 1769 | LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address); | 1768 | LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address); |
| 1770 | return ResultInvalidCurrentMemory; | 1769 | return ResultInvalidCurrentMemory; |
| 1771 | } | 1770 | } |
| @@ -1887,9 +1886,8 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd | |||
| 1887 | return ResultInvalidCurrentMemory; | 1886 | return ResultInvalidCurrentMemory; |
| 1888 | } | 1887 | } |
| 1889 | 1888 | ||
| 1890 | const auto perms{static_cast<Memory::MemoryPermission>(permissions)}; | 1889 | const auto perms{static_cast<MemoryPermission>(permissions)}; |
| 1891 | if (perms > Memory::MemoryPermission::ReadAndWrite || | 1890 | if (perms > MemoryPermission::ReadWrite || perms == MemoryPermission::Write) { |
| 1892 | perms == Memory::MemoryPermission::Write) { | ||
| 1893 | LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", | 1891 | LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", |
| 1894 | permissions); | 1892 | permissions); |
| 1895 | return ResultInvalidMemoryPermissions; | 1893 | return ResultInvalidMemoryPermissions; |
| @@ -1903,7 +1901,8 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd | |||
| 1903 | LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); | 1901 | LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); |
| 1904 | return ResultResourceLimitedExceeded; | 1902 | return ResultResourceLimitedExceeded; |
| 1905 | } | 1903 | } |
| 1906 | auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms); | 1904 | auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, |
| 1905 | static_cast<KMemoryPermission>(perms)); | ||
| 1907 | 1906 | ||
| 1908 | if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { | 1907 | if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { |
| 1909 | return reserve_result; | 1908 | return reserve_result; |
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp index 6b0fc1591..cad063e4d 100644 --- a/src/core/hle/kernel/transfer_memory.cpp +++ b/src/core/hle/kernel/transfer_memory.cpp | |||
| @@ -2,9 +2,9 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/hle/kernel/k_page_table.h" | ||
| 5 | #include "core/hle/kernel/k_resource_limit.h" | 6 | #include "core/hle/kernel/k_resource_limit.h" |
| 6 | #include "core/hle/kernel/kernel.h" | 7 | #include "core/hle/kernel/kernel.h" |
| 7 | #include "core/hle/kernel/memory/page_table.h" | ||
| 8 | #include "core/hle/kernel/process.h" | 8 | #include "core/hle/kernel/process.h" |
| 9 | #include "core/hle/kernel/transfer_memory.h" | 9 | #include "core/hle/kernel/transfer_memory.h" |
| 10 | #include "core/hle/result.h" | 10 | #include "core/hle/result.h" |
| @@ -24,7 +24,7 @@ TransferMemory::~TransferMemory() { | |||
| 24 | std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, | 24 | std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, |
| 25 | Core::Memory::Memory& memory, | 25 | Core::Memory::Memory& memory, |
| 26 | VAddr base_address, std::size_t size, | 26 | VAddr base_address, std::size_t size, |
| 27 | Memory::MemoryPermission permissions) { | 27 | KMemoryPermission permissions) { |
| 28 | std::shared_ptr<TransferMemory> transfer_memory{ | 28 | std::shared_ptr<TransferMemory> transfer_memory{ |
| 29 | std::make_shared<TransferMemory>(kernel, memory)}; | 29 | std::make_shared<TransferMemory>(kernel, memory)}; |
| 30 | 30 | ||
diff --git a/src/core/hle/kernel/transfer_memory.h b/src/core/hle/kernel/transfer_memory.h index 777799d12..521951424 100644 --- a/src/core/hle/kernel/transfer_memory.h +++ b/src/core/hle/kernel/transfer_memory.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | 8 | ||
| 9 | #include "core/hle/kernel/memory/memory_block.h" | 9 | #include "core/hle/kernel/k_memory_block.h" |
| 10 | #include "core/hle/kernel/object.h" | 10 | #include "core/hle/kernel/object.h" |
| 11 | #include "core/hle/kernel/physical_memory.h" | 11 | #include "core/hle/kernel/physical_memory.h" |
| 12 | 12 | ||
| @@ -36,7 +36,7 @@ public: | |||
| 36 | 36 | ||
| 37 | static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, Core::Memory::Memory& memory, | 37 | static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, Core::Memory::Memory& memory, |
| 38 | VAddr base_address, std::size_t size, | 38 | VAddr base_address, std::size_t size, |
| 39 | Memory::MemoryPermission permissions); | 39 | KMemoryPermission permissions); |
| 40 | 40 | ||
| 41 | TransferMemory(const TransferMemory&) = delete; | 41 | TransferMemory(const TransferMemory&) = delete; |
| 42 | TransferMemory& operator=(const TransferMemory&) = delete; | 42 | TransferMemory& operator=(const TransferMemory&) = delete; |
| @@ -82,7 +82,7 @@ private: | |||
| 82 | std::size_t size{}; | 82 | std::size_t size{}; |
| 83 | 83 | ||
| 84 | /// The memory permissions that are applied to this instance. | 84 | /// The memory permissions that are applied to this instance. |
| 85 | Memory::MemoryPermission owner_permissions{}; | 85 | KMemoryPermission owner_permissions{}; |
| 86 | 86 | ||
| 87 | /// The process that this transfer memory instance was created under. | 87 | /// The process that this transfer memory instance was created under. |
| 88 | Process* owner_process{}; | 88 | Process* owner_process{}; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 3d0fe42f6..ba27bbb05 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -15,9 +15,9 @@ | |||
| 15 | #include "core/hle/kernel/client_port.h" | 15 | #include "core/hle/kernel/client_port.h" |
| 16 | #include "core/hle/kernel/client_session.h" | 16 | #include "core/hle/kernel/client_session.h" |
| 17 | #include "core/hle/kernel/k_readable_event.h" | 17 | #include "core/hle/kernel/k_readable_event.h" |
| 18 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 18 | #include "core/hle/kernel/k_writable_event.h" | 19 | #include "core/hle/kernel/k_writable_event.h" |
| 19 | #include "core/hle/kernel/kernel.h" | 20 | #include "core/hle/kernel/kernel.h" |
| 20 | #include "core/hle/kernel/shared_memory.h" | ||
| 21 | #include "core/hle/service/hid/errors.h" | 21 | #include "core/hle/service/hid/errors.h" |
| 22 | #include "core/hle/service/hid/hid.h" | 22 | #include "core/hle/service/hid/hid.h" |
| 23 | #include "core/hle/service/hid/irs.h" | 23 | #include "core/hle/service/hid/irs.h" |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 99d155586..36ed228c8 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -14,7 +14,7 @@ struct EventType; | |||
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | namespace Kernel { | 16 | namespace Kernel { |
| 17 | class SharedMemory; | 17 | class KSharedMemory; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | namespace Service::SM { | 20 | namespace Service::SM { |
| @@ -69,7 +69,7 @@ private: | |||
| 69 | void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 69 | void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 70 | void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); | 70 | void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late); |
| 71 | 71 | ||
| 72 | std::shared_ptr<Kernel::SharedMemory> shared_mem; | 72 | std::shared_ptr<Kernel::KSharedMemory> shared_mem; |
| 73 | 73 | ||
| 74 | std::shared_ptr<Core::Timing::EventType> pad_update_event; | 74 | std::shared_ptr<Core::Timing::EventType> pad_update_event; |
| 75 | std::shared_ptr<Core::Timing::EventType> motion_update_event; | 75 | std::shared_ptr<Core::Timing::EventType> motion_update_event; |
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index c8413099f..2dfa936fb 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | #include "core/core.h" | 6 | #include "core/core.h" |
| 7 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| 8 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 9 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 10 | #include "core/hle/kernel/shared_memory.h" | ||
| 11 | #include "core/hle/service/hid/irs.h" | 11 | #include "core/hle/service/hid/irs.h" |
| 12 | 12 | ||
| 13 | namespace Service::HID { | 13 | namespace Service::HID { |
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index be0c486ba..b0c8c7168 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h | |||
| @@ -12,7 +12,7 @@ class System; | |||
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | class SharedMemory; | 15 | class KSharedMemory; |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | namespace Service::HID { | 18 | namespace Service::HID { |
| @@ -42,7 +42,7 @@ private: | |||
| 42 | void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); | 42 | void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); |
| 43 | void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); | 43 | void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); |
| 44 | 44 | ||
| 45 | std::shared_ptr<Kernel::SharedMemory> shared_mem; | 45 | std::shared_ptr<Kernel::KSharedMemory> shared_mem; |
| 46 | const u32 device_handle{0xABCD}; | 46 | const u32 device_handle{0xABCD}; |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index c724d2554..d111c1357 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp | |||
| @@ -11,8 +11,8 @@ | |||
| 11 | #include "common/scope_exit.h" | 11 | #include "common/scope_exit.h" |
| 12 | #include "core/core.h" | 12 | #include "core/core.h" |
| 13 | #include "core/hle/ipc_helpers.h" | 13 | #include "core/hle/ipc_helpers.h" |
| 14 | #include "core/hle/kernel/memory/page_table.h" | 14 | #include "core/hle/kernel/k_page_table.h" |
| 15 | #include "core/hle/kernel/memory/system_control.h" | 15 | #include "core/hle/kernel/k_system_control.h" |
| 16 | #include "core/hle/kernel/process.h" | 16 | #include "core/hle/kernel/process.h" |
| 17 | #include "core/hle/kernel/svc_results.h" | 17 | #include "core/hle/kernel/svc_results.h" |
| 18 | #include "core/hle/service/ldr/ldr.h" | 18 | #include "core/hle/service/ldr/ldr.h" |
| @@ -287,12 +287,11 @@ public: | |||
| 287 | rb.Push(RESULT_SUCCESS); | 287 | rb.Push(RESULT_SUCCESS); |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | bool ValidateRegionForMap(Kernel::Memory::PageTable& page_table, VAddr start, | 290 | bool ValidateRegionForMap(Kernel::KPageTable& page_table, VAddr start, std::size_t size) const { |
| 291 | std::size_t size) const { | 291 | constexpr std::size_t padding_size{4 * Kernel::PageSize}; |
| 292 | constexpr std::size_t padding_size{4 * Kernel::Memory::PageSize}; | ||
| 293 | const auto start_info{page_table.QueryInfo(start - 1)}; | 292 | const auto start_info{page_table.QueryInfo(start - 1)}; |
| 294 | 293 | ||
| 295 | if (start_info.state != Kernel::Memory::MemoryState::Free) { | 294 | if (start_info.state != Kernel::KMemoryState::Free) { |
| 296 | return {}; | 295 | return {}; |
| 297 | } | 296 | } |
| 298 | 297 | ||
| @@ -302,21 +301,20 @@ public: | |||
| 302 | 301 | ||
| 303 | const auto end_info{page_table.QueryInfo(start + size)}; | 302 | const auto end_info{page_table.QueryInfo(start + size)}; |
| 304 | 303 | ||
| 305 | if (end_info.state != Kernel::Memory::MemoryState::Free) { | 304 | if (end_info.state != Kernel::KMemoryState::Free) { |
| 306 | return {}; | 305 | return {}; |
| 307 | } | 306 | } |
| 308 | 307 | ||
| 309 | return (start + size + padding_size) <= (end_info.GetAddress() + end_info.GetSize()); | 308 | return (start + size + padding_size) <= (end_info.GetAddress() + end_info.GetSize()); |
| 310 | } | 309 | } |
| 311 | 310 | ||
| 312 | VAddr GetRandomMapRegion(const Kernel::Memory::PageTable& page_table, std::size_t size) const { | 311 | VAddr GetRandomMapRegion(const Kernel::KPageTable& page_table, std::size_t size) const { |
| 313 | VAddr addr{}; | 312 | VAddr addr{}; |
| 314 | const std::size_t end_pages{(page_table.GetAliasCodeRegionSize() - size) >> | 313 | const std::size_t end_pages{(page_table.GetAliasCodeRegionSize() - size) >> |
| 315 | Kernel::Memory::PageBits}; | 314 | Kernel::PageBits}; |
| 316 | do { | 315 | do { |
| 317 | addr = page_table.GetAliasCodeRegionStart() + | 316 | addr = page_table.GetAliasCodeRegionStart() + |
| 318 | (Kernel::Memory::SystemControl::GenerateRandomRange(0, end_pages) | 317 | (Kernel::KSystemControl::GenerateRandomRange(0, end_pages) << Kernel::PageBits); |
| 319 | << Kernel::Memory::PageBits); | ||
| 320 | } while (!page_table.IsInsideAddressSpace(addr, size) || | 318 | } while (!page_table.IsInsideAddressSpace(addr, size) || |
| 321 | page_table.IsInsideHeapRegion(addr, size) || | 319 | page_table.IsInsideHeapRegion(addr, size) || |
| 322 | page_table.IsInsideAliasRegion(addr, size)); | 320 | page_table.IsInsideAliasRegion(addr, size)); |
| @@ -387,7 +385,7 @@ public: | |||
| 387 | const VAddr data_start{start + nro_header.segment_headers[DATA_INDEX].memory_offset}; | 385 | const VAddr data_start{start + nro_header.segment_headers[DATA_INDEX].memory_offset}; |
| 388 | const VAddr bss_start{data_start + nro_header.segment_headers[DATA_INDEX].memory_size}; | 386 | const VAddr bss_start{data_start + nro_header.segment_headers[DATA_INDEX].memory_size}; |
| 389 | const VAddr bss_end_addr{ | 387 | const VAddr bss_end_addr{ |
| 390 | Common::AlignUp(bss_start + nro_header.bss_size, Kernel::Memory::PageSize)}; | 388 | Common::AlignUp(bss_start + nro_header.bss_size, Kernel::PageSize)}; |
| 391 | 389 | ||
| 392 | auto CopyCode{[&](VAddr src_addr, VAddr dst_addr, u64 size) { | 390 | auto CopyCode{[&](VAddr src_addr, VAddr dst_addr, u64 size) { |
| 393 | std::vector<u8> source_data(size); | 391 | std::vector<u8> source_data(size); |
| @@ -402,12 +400,12 @@ public: | |||
| 402 | nro_header.segment_headers[DATA_INDEX].memory_size); | 400 | nro_header.segment_headers[DATA_INDEX].memory_size); |
| 403 | 401 | ||
| 404 | CASCADE_CODE(process->PageTable().SetCodeMemoryPermission( | 402 | CASCADE_CODE(process->PageTable().SetCodeMemoryPermission( |
| 405 | text_start, ro_start - text_start, Kernel::Memory::MemoryPermission::ReadAndExecute)); | 403 | text_start, ro_start - text_start, Kernel::KMemoryPermission::ReadAndExecute)); |
| 406 | CASCADE_CODE(process->PageTable().SetCodeMemoryPermission( | 404 | CASCADE_CODE(process->PageTable().SetCodeMemoryPermission(ro_start, data_start - ro_start, |
| 407 | ro_start, data_start - ro_start, Kernel::Memory::MemoryPermission::Read)); | 405 | Kernel::KMemoryPermission::Read)); |
| 408 | 406 | ||
| 409 | return process->PageTable().SetCodeMemoryPermission( | 407 | return process->PageTable().SetCodeMemoryPermission( |
| 410 | data_start, bss_end_addr - data_start, Kernel::Memory::MemoryPermission::ReadAndWrite); | 408 | data_start, bss_end_addr - data_start, Kernel::KMemoryPermission::ReadAndWrite); |
| 411 | } | 409 | } |
| 412 | 410 | ||
| 413 | void LoadNro(Kernel::HLERequestContext& ctx) { | 411 | void LoadNro(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index b6ac0a81a..fcd15d81f 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp | |||
| @@ -19,9 +19,9 @@ | |||
| 19 | #include "core/file_sys/romfs.h" | 19 | #include "core/file_sys/romfs.h" |
| 20 | #include "core/file_sys/system_archive/system_archive.h" | 20 | #include "core/file_sys/system_archive/system_archive.h" |
| 21 | #include "core/hle/ipc_helpers.h" | 21 | #include "core/hle/ipc_helpers.h" |
| 22 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 22 | #include "core/hle/kernel/kernel.h" | 23 | #include "core/hle/kernel/kernel.h" |
| 23 | #include "core/hle/kernel/physical_memory.h" | 24 | #include "core/hle/kernel/physical_memory.h" |
| 24 | #include "core/hle/kernel/shared_memory.h" | ||
| 25 | #include "core/hle/service/filesystem/filesystem.h" | 25 | #include "core/hle/service/filesystem/filesystem.h" |
| 26 | #include "core/hle/service/ns/pl_u.h" | 26 | #include "core/hle/service/ns/pl_u.h" |
| 27 | 27 | ||
| @@ -131,7 +131,7 @@ struct PL_U::Impl { | |||
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | /// Handle to shared memory region designated for a shared font | 133 | /// Handle to shared memory region designated for a shared font |
| 134 | std::shared_ptr<Kernel::SharedMemory> shared_font_mem; | 134 | std::shared_ptr<Kernel::KSharedMemory> shared_font_mem; |
| 135 | 135 | ||
| 136 | /// Backing memory for the shared font data | 136 | /// Backing memory for the shared font data |
| 137 | std::shared_ptr<Kernel::PhysicalMemory> shared_font; | 137 | std::shared_ptr<Kernel::PhysicalMemory> shared_font; |
diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp index e0ae9f874..4d8de81be 100644 --- a/src/core/hle/service/time/time_sharedmemory.cpp +++ b/src/core/hle/service/time/time_sharedmemory.cpp | |||
| @@ -22,7 +22,7 @@ SharedMemory::SharedMemory(Core::System& system) : system(system) { | |||
| 22 | 22 | ||
| 23 | SharedMemory::~SharedMemory() = default; | 23 | SharedMemory::~SharedMemory() = default; |
| 24 | 24 | ||
| 25 | std::shared_ptr<Kernel::SharedMemory> SharedMemory::GetSharedMemoryHolder() const { | 25 | std::shared_ptr<Kernel::KSharedMemory> SharedMemory::GetSharedMemoryHolder() const { |
| 26 | return shared_memory_holder; | 26 | return shared_memory_holder; |
| 27 | } | 27 | } |
| 28 | 28 | ||
diff --git a/src/core/hle/service/time/time_sharedmemory.h b/src/core/hle/service/time/time_sharedmemory.h index e0c3e63da..299680517 100644 --- a/src/core/hle/service/time/time_sharedmemory.h +++ b/src/core/hle/service/time/time_sharedmemory.h | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 8 | #include "common/uuid.h" | 8 | #include "common/uuid.h" |
| 9 | #include "core/hle/kernel/k_shared_memory.h" | ||
| 9 | #include "core/hle/kernel/k_thread.h" | 10 | #include "core/hle/kernel/k_thread.h" |
| 10 | #include "core/hle/kernel/shared_memory.h" | ||
| 11 | #include "core/hle/service/time/clock_types.h" | 11 | #include "core/hle/service/time/clock_types.h" |
| 12 | 12 | ||
| 13 | namespace Service::Time { | 13 | namespace Service::Time { |
| @@ -18,7 +18,7 @@ public: | |||
| 18 | ~SharedMemory(); | 18 | ~SharedMemory(); |
| 19 | 19 | ||
| 20 | // Return the shared memory handle | 20 | // Return the shared memory handle |
| 21 | std::shared_ptr<Kernel::SharedMemory> GetSharedMemoryHolder() const; | 21 | std::shared_ptr<Kernel::KSharedMemory> GetSharedMemoryHolder() const; |
| 22 | 22 | ||
| 23 | // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this? | 23 | // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this? |
| 24 | template <typename T, std::size_t Offset> | 24 | template <typename T, std::size_t Offset> |
| @@ -63,7 +63,7 @@ public: | |||
| 63 | void SetAutomaticCorrectionEnabled(bool is_enabled); | 63 | void SetAutomaticCorrectionEnabled(bool is_enabled); |
| 64 | 64 | ||
| 65 | private: | 65 | private: |
| 66 | std::shared_ptr<Kernel::SharedMemory> shared_memory_holder; | 66 | std::shared_ptr<Kernel::KSharedMemory> shared_memory_holder; |
| 67 | Core::System& system; | 67 | Core::System& system; |
| 68 | Format shared_memory_format{}; | 68 | Format shared_memory_format{}; |
| 69 | }; | 69 | }; |
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 79ebf11de..4a10211f6 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | #include "core/file_sys/control_metadata.h" | 12 | #include "core/file_sys/control_metadata.h" |
| 13 | #include "core/file_sys/patch_manager.h" | 13 | #include "core/file_sys/patch_manager.h" |
| 14 | #include "core/file_sys/romfs_factory.h" | 14 | #include "core/file_sys/romfs_factory.h" |
| 15 | #include "core/hle/kernel/k_page_table.h" | ||
| 15 | #include "core/hle/kernel/kernel.h" | 16 | #include "core/hle/kernel/kernel.h" |
| 16 | #include "core/hle/kernel/memory/page_table.h" | ||
| 17 | #include "core/hle/kernel/process.h" | 17 | #include "core/hle/kernel/process.h" |
| 18 | #include "core/hle/service/filesystem/filesystem.h" | 18 | #include "core/hle/service/filesystem/filesystem.h" |
| 19 | #include "core/loader/deconstructed_rom_directory.h" | 19 | #include "core/loader/deconstructed_rom_directory.h" |
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index dca1fcb18..f4a339390 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "common/file_util.h" | 10 | #include "common/file_util.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "core/hle/kernel/code_set.h" | 12 | #include "core/hle/kernel/code_set.h" |
| 13 | #include "core/hle/kernel/memory/page_table.h" | 13 | #include "core/hle/kernel/k_page_table.h" |
| 14 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/process.h" |
| 15 | #include "core/loader/elf.h" | 15 | #include "core/loader/elf.h" |
| 16 | #include "core/memory.h" | 16 | #include "core/memory.h" |
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp index e162c4ff0..3f4ba233d 100644 --- a/src/core/loader/kip.cpp +++ b/src/core/loader/kip.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include "core/file_sys/kernel_executable.h" | 6 | #include "core/file_sys/kernel_executable.h" |
| 7 | #include "core/file_sys/program_metadata.h" | 7 | #include "core/file_sys/program_metadata.h" |
| 8 | #include "core/hle/kernel/code_set.h" | 8 | #include "core/hle/kernel/code_set.h" |
| 9 | #include "core/hle/kernel/memory/page_table.h" | 9 | #include "core/hle/kernel/k_page_table.h" |
| 10 | #include "core/hle/kernel/process.h" | 10 | #include "core/hle/kernel/process.h" |
| 11 | #include "core/loader/kip.h" | 11 | #include "core/loader/kip.h" |
| 12 | #include "core/memory.h" | 12 | #include "core/memory.h" |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index f976d0a9c..14618cb40 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -15,8 +15,8 @@ | |||
| 15 | #include "core/file_sys/romfs_factory.h" | 15 | #include "core/file_sys/romfs_factory.h" |
| 16 | #include "core/file_sys/vfs_offset.h" | 16 | #include "core/file_sys/vfs_offset.h" |
| 17 | #include "core/hle/kernel/code_set.h" | 17 | #include "core/hle/kernel/code_set.h" |
| 18 | #include "core/hle/kernel/k_page_table.h" | ||
| 18 | #include "core/hle/kernel/k_thread.h" | 19 | #include "core/hle/kernel/k_thread.h" |
| 19 | #include "core/hle/kernel/memory/page_table.h" | ||
| 20 | #include "core/hle/kernel/process.h" | 20 | #include "core/hle/kernel/process.h" |
| 21 | #include "core/hle/service/filesystem/filesystem.h" | 21 | #include "core/hle/service/filesystem/filesystem.h" |
| 22 | #include "core/loader/nro.h" | 22 | #include "core/loader/nro.h" |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index ea347ea83..cbd048695 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -15,8 +15,8 @@ | |||
| 15 | #include "core/core.h" | 15 | #include "core/core.h" |
| 16 | #include "core/file_sys/patch_manager.h" | 16 | #include "core/file_sys/patch_manager.h" |
| 17 | #include "core/hle/kernel/code_set.h" | 17 | #include "core/hle/kernel/code_set.h" |
| 18 | #include "core/hle/kernel/k_page_table.h" | ||
| 18 | #include "core/hle/kernel/k_thread.h" | 19 | #include "core/hle/kernel/k_thread.h" |
| 19 | #include "core/hle/kernel/memory/page_table.h" | ||
| 20 | #include "core/hle/kernel/process.h" | 20 | #include "core/hle/kernel/process.h" |
| 21 | #include "core/loader/nso.h" | 21 | #include "core/loader/nso.h" |
| 22 | #include "core/memory.h" | 22 | #include "core/memory.h" |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 11609682a..b9dd3e275 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include "core/arm/arm_interface.h" | 16 | #include "core/arm/arm_interface.h" |
| 17 | #include "core/core.h" | 17 | #include "core/core.h" |
| 18 | #include "core/device_memory.h" | 18 | #include "core/device_memory.h" |
| 19 | #include "core/hle/kernel/memory/page_table.h" | 19 | #include "core/hle/kernel/k_page_table.h" |
| 20 | #include "core/hle/kernel/physical_memory.h" | 20 | #include "core/hle/kernel/physical_memory.h" |
| 21 | #include "core/hle/kernel/process.h" | 21 | #include "core/hle/kernel/process.h" |
| 22 | #include "core/memory.h" | 22 | #include "core/memory.h" |
diff --git a/src/core/memory.h b/src/core/memory.h index 705ebb23d..6d34fcfe2 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -116,6 +116,11 @@ public: | |||
| 116 | */ | 116 | */ |
| 117 | u8* GetPointer(VAddr vaddr); | 117 | u8* GetPointer(VAddr vaddr); |
| 118 | 118 | ||
| 119 | template <typename T> | ||
| 120 | T* GetPointer(VAddr vaddr) { | ||
| 121 | return reinterpret_cast<T*>(GetPointer(vaddr)); | ||
| 122 | } | ||
| 123 | |||
| 119 | /** | 124 | /** |
| 120 | * Gets a pointer to the given address. | 125 | * Gets a pointer to the given address. |
| 121 | * | 126 | * |
| @@ -126,6 +131,11 @@ public: | |||
| 126 | */ | 131 | */ |
| 127 | const u8* GetPointer(VAddr vaddr) const; | 132 | const u8* GetPointer(VAddr vaddr) const; |
| 128 | 133 | ||
| 134 | template <typename T> | ||
| 135 | const T* GetPointer(VAddr vaddr) const { | ||
| 136 | return reinterpret_cast<T*>(GetPointer(vaddr)); | ||
| 137 | } | ||
| 138 | |||
| 129 | /** | 139 | /** |
| 130 | * Reads an 8-bit unsigned value from the current process' address space | 140 | * Reads an 8-bit unsigned value from the current process' address space |
| 131 | * at the given virtual address. | 141 | * at the given virtual address. |
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 2dd0eb0f8..8eec567ab 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #include "core/core_timing.h" | 10 | #include "core/core_timing.h" |
| 11 | #include "core/core_timing_util.h" | 11 | #include "core/core_timing_util.h" |
| 12 | #include "core/hardware_properties.h" | 12 | #include "core/hardware_properties.h" |
| 13 | #include "core/hle/kernel/memory/page_table.h" | 13 | #include "core/hle/kernel/k_page_table.h" |
| 14 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/process.h" |
| 15 | #include "core/hle/service/hid/controllers/npad.h" | 15 | #include "core/hle/service/hid/controllers/npad.h" |
| 16 | #include "core/hle/service/hid/hid.h" | 16 | #include "core/hle/service/hid/hid.h" |
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index f199c3362..74fb32814 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #include "core/arm/arm_interface.h" | 17 | #include "core/arm/arm_interface.h" |
| 18 | #include "core/core.h" | 18 | #include "core/core.h" |
| 19 | #include "core/hle/kernel/hle_ipc.h" | 19 | #include "core/hle/kernel/hle_ipc.h" |
| 20 | #include "core/hle/kernel/memory/page_table.h" | 20 | #include "core/hle/kernel/k_page_table.h" |
| 21 | #include "core/hle/kernel/process.h" | 21 | #include "core/hle/kernel/process.h" |
| 22 | #include "core/hle/result.h" | 22 | #include "core/hle/result.h" |
| 23 | #include "core/memory.h" | 23 | #include "core/memory.h" |
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 44240a9c4..4eb71efbd 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/hle/kernel/memory/page_table.h" | 9 | #include "core/hle/kernel/k_page_table.h" |
| 10 | #include "core/hle/kernel/process.h" | 10 | #include "core/hle/kernel/process.h" |
| 11 | #include "core/memory.h" | 11 | #include "core/memory.h" |
| 12 | #include "video_core/gpu.h" | 12 | #include "video_core/gpu.h" |