summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules2
m---------externals/dynarmic0
m---------externals/mbedtls0
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/alignment.h5
-rw-r--r--src/common/cityhash.h1
-rw-r--r--src/common/common_funcs.h6
-rw-r--r--src/common/fiber.cpp23
-rw-r--r--src/common/fiber.h2
-rw-r--r--src/common/misc.cpp44
-rw-r--r--src/common/tiny_mt.h250
-rw-r--r--src/core/CMakeLists.txt41
-rw-r--r--src/core/core.cpp13
-rw-r--r--src/core/cpu_manager.cpp8
-rw-r--r--src/core/crypto/aes_util.cpp2
-rw-r--r--src/core/hle/kernel/k_address_space_info.cpp (renamed from src/core/hle/kernel/memory/address_space_info.cpp)60
-rw-r--r--src/core/hle/kernel/k_address_space_info.h (renamed from src/core/hle/kernel/memory/address_space_info.h)15
-rw-r--r--src/core/hle/kernel/k_memory_block.h (renamed from src/core/hle/kernel/memory/memory_block.h)149
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.cpp (renamed from src/core/hle/kernel/memory/memory_block_manager.cpp)60
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.h (renamed from src/core/hle/kernel/memory/memory_block_manager.h)33
-rw-r--r--src/core/hle/kernel/k_memory_layout.h (renamed from src/core/hle/kernel/memory/memory_layout.h)34
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp (renamed from src/core/hle/kernel/memory/memory_manager.cpp)39
-rw-r--r--src/core/hle/kernel/k_memory_manager.h (renamed from src/core/hle/kernel/memory/memory_manager.h)49
-rw-r--r--src/core/hle/kernel/k_page_bitmap.h279
-rw-r--r--src/core/hle/kernel/k_page_heap.cpp (renamed from src/core/hle/kernel/memory/page_heap.cpp)23
-rw-r--r--src/core/hle/kernel/k_page_heap.h193
-rw-r--r--src/core/hle/kernel/k_page_linked_list.h (renamed from src/core/hle/kernel/memory/page_linked_list.h)14
-rw-r--r--src/core/hle/kernel/k_page_table.cpp (renamed from src/core/hle/kernel/memory/page_table.cpp)592
-rw-r--r--src/core/hle/kernel/k_page_table.h (renamed from src/core/hle/kernel/memory/page_table.h)98
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp17
-rw-r--r--src/core/hle/kernel/k_shared_memory.cpp (renamed from src/core/hle/kernel/shared_memory.cpp)29
-rw-r--r--src/core/hle/kernel/k_shared_memory.h (renamed from src/core/hle/kernel/shared_memory.h)24
-rw-r--r--src/core/hle/kernel/k_slab_heap.h (renamed from src/core/hle/kernel/memory/slab_heap.h)21
-rw-r--r--src/core/hle/kernel/k_spin_lock.cpp54
-rw-r--r--src/core/hle/kernel/k_spin_lock.h33
-rw-r--r--src/core/hle/kernel/k_system_control.cpp (renamed from src/core/hle/kernel/memory/system_control.cpp)18
-rw-r--r--src/core/hle/kernel/k_system_control.h19
-rw-r--r--src/core/hle/kernel/k_thread.cpp58
-rw-r--r--src/core/hle/kernel/k_thread.h24
-rw-r--r--src/core/hle/kernel/kernel.cpp99
-rw-r--r--src/core/hle/kernel/kernel.h44
-rw-r--r--src/core/hle/kernel/memory/page_heap.h370
-rw-r--r--src/core/hle/kernel/memory/system_control.h13
-rw-r--r--src/core/hle/kernel/memory_types.h (renamed from src/core/hle/kernel/memory/memory_types.h)4
-rw-r--r--src/core/hle/kernel/process.cpp63
-rw-r--r--src/core/hle/kernel/process.h11
-rw-r--r--src/core/hle/kernel/process_capability.cpp14
-rw-r--r--src/core/hle/kernel/process_capability.h16
-rw-r--r--src/core/hle/kernel/svc.cpp56
-rw-r--r--src/core/hle/kernel/transfer_memory.cpp4
-rw-r--r--src/core/hle/kernel/transfer_memory.h6
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp159
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h92
-rw-r--r--src/core/hle/service/hid/hid.cpp2
-rw-r--r--src/core/hle/service/hid/hid.h4
-rw-r--r--src/core/hle/service/hid/irs.cpp2
-rw-r--r--src/core/hle/service/hid/irs.h4
-rw-r--r--src/core/hle/service/ldn/ldn.cpp2
-rw-r--r--src/core/hle/service/ldr/ldr.cpp30
-rw-r--r--src/core/hle/service/ns/pl_u.cpp4
-rw-r--r--src/core/hle/service/time/time_sharedmemory.cpp2
-rw-r--r--src/core/hle/service/time/time_sharedmemory.h6
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp2
-rw-r--r--src/core/loader/elf.cpp2
-rw-r--r--src/core/loader/kip.cpp2
-rw-r--r--src/core/loader/nro.cpp2
-rw-r--r--src/core/loader/nso.cpp2
-rw-r--r--src/core/memory.cpp2
-rw-r--r--src/core/memory.h10
-rw-r--r--src/core/memory/cheat_engine.cpp2
-rw-r--r--src/core/network/network.cpp173
-rw-r--r--src/core/network/network.h6
-rw-r--r--src/core/reporter.cpp2
-rw-r--r--src/input_common/udp/client.cpp26
-rw-r--r--src/input_common/udp/client.h6
-rw-r--r--src/tests/CMakeLists.txt1
-rw-r--r--src/tests/common/fibers.cpp28
-rw-r--r--src/tests/core/network/network.cpp28
-rw-r--r--src/video_core/gpu.cpp2
-rw-r--r--src/video_core/gpu_thread.cpp13
-rw-r--r--src/video_core/gpu_thread.h19
-rw-r--r--src/video_core/memory_manager.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_command_pool.cpp2
-rw-r--r--src/video_core/shader_notify.cpp1
-rw-r--r--src/yuzu/configuration/config.cpp4
-rw-r--r--src/yuzu/configuration/configure_motion_touch.cpp8
-rw-r--r--src/yuzu/configuration/configure_motion_touch.h2
-rw-r--r--src/yuzu_cmd/config.cpp2
89 files changed, 2219 insertions, 1472 deletions
diff --git a/.gitmodules b/.gitmodules
index 93ba9b930..a0a89933d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -27,7 +27,7 @@
27 url = https://github.com/ReinUsesLisp/sirit 27 url = https://github.com/ReinUsesLisp/sirit
28[submodule "mbedtls"] 28[submodule "mbedtls"]
29 path = externals/mbedtls 29 path = externals/mbedtls
30 url = https://github.com/DarkLordZach/mbedtls 30 url = https://github.com/yuzu-emu/mbedtls
31[submodule "libzip"] 31[submodule "libzip"]
32 path = externals/libzip/libzip 32 path = externals/libzip/libzip
33 url = https://github.com/nih-at/libzip.git 33 url = https://github.com/nih-at/libzip.git
diff --git a/externals/dynarmic b/externals/dynarmic
Subproject cafa687684a3e5dbe86be7150c0f8183d2ad53c Subproject 646fd0592091c5c1e5899fa715bd7b7fcc977a3
diff --git a/externals/mbedtls b/externals/mbedtls
Subproject a280e602f3a4ae001d3a83cbc3e6e04c99c2227 Subproject eac2416b8fdb2cb9c867a538100bf95326bad75
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1cfd3bbc9..8bd7e5f72 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -27,6 +27,7 @@ if (MSVC)
27 # /Zo - Enhanced debug info for optimized builds 27 # /Zo - Enhanced debug info for optimized builds
28 # /permissive- - Enables stricter C++ standards conformance checks 28 # /permissive- - Enables stricter C++ standards conformance checks
29 # /EHsc - C++-only exception handling semantics 29 # /EHsc - C++-only exception handling semantics
30 # /utf-8 - Set source and execution character sets to UTF-8
30 # /volatile:iso - Use strict standards-compliant volatile semantics. 31 # /volatile:iso - Use strict standards-compliant volatile semantics.
31 # /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates 32 # /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates
32 # /Zc:inline - Let codegen omit inline functions in object files 33 # /Zc:inline - Let codegen omit inline functions in object files
@@ -38,6 +39,7 @@ if (MSVC)
38 /permissive- 39 /permissive-
39 /EHsc 40 /EHsc
40 /std:c++latest 41 /std:c++latest
42 /utf-8
41 /volatile:iso 43 /volatile:iso
42 /Zc:externConstexpr 44 /Zc:externConstexpr
43 /Zc:inline 45 /Zc:inline
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
45template <typename T, typename U>
46requires std::is_integral_v<T>[[nodiscard]] constexpr T DivideUp(T x, U y) {
47 return (x + (y - 1)) / y;
48}
49
45template <typename T, size_t Align = 16> 50template <typename T, size_t Align = 16>
46class AlignmentAllocator { 51class AlignmentAllocator {
47public: 52public:
diff --git a/src/common/cityhash.h b/src/common/cityhash.h
index 022d0f7cb..d74fc7639 100644
--- a/src/common/cityhash.h
+++ b/src/common/cityhash.h
@@ -61,6 +61,7 @@
61 61
62#pragma once 62#pragma once
63 63
64#include <cstddef>
64#include "common/common_types.h" 65#include "common/common_types.h"
65 66
66namespace Common { 67namespace Common {
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index 71b64e32a..4ace2cd33 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -52,9 +52,13 @@ __declspec(dllimport) void __stdcall DebugBreak(void);
52// Generic function to get last error message. 52// Generic function to get last error message.
53// Call directly after the command or use the error num. 53// Call directly after the command or use the error num.
54// This function might change the error code. 54// This function might change the error code.
55// Defined in Misc.cpp. 55// Defined in misc.cpp.
56[[nodiscard]] std::string GetLastErrorMsg(); 56[[nodiscard]] std::string GetLastErrorMsg();
57 57
58// Like GetLastErrorMsg(), but passing an explicit error code.
59// Defined in misc.cpp.
60[[nodiscard]] std::string NativeErrorToString(int e);
61
58#define DECLARE_ENUM_FLAG_OPERATORS(type) \ 62#define DECLARE_ENUM_FLAG_OPERATORS(type) \
59 [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \ 63 [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \
60 using T = std::underlying_type_t<type>; \ 64 using T = std::underlying_type_t<type>; \
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index 3c1eefcb7..39532ff58 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -116,16 +116,19 @@ void Fiber::Rewind() {
116 boost::context::detail::jump_fcontext(impl->rewind_context, this); 116 boost::context::detail::jump_fcontext(impl->rewind_context, this);
117} 117}
118 118
119void Fiber::YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to) { 119void Fiber::YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to) {
120 ASSERT_MSG(from != nullptr, "Yielding fiber is null!"); 120 to.impl->guard.lock();
121 ASSERT_MSG(to != nullptr, "Next fiber is null!"); 121 to.impl->previous_fiber = weak_from.lock();
122 to->impl->guard.lock(); 122
123 to->impl->previous_fiber = from; 123 auto transfer = boost::context::detail::jump_fcontext(to.impl->context, &to);
124 auto transfer = boost::context::detail::jump_fcontext(to->impl->context, to.get()); 124
125 ASSERT(from->impl->previous_fiber != nullptr); 125 // "from" might no longer be valid if the thread was killed
126 from->impl->previous_fiber->impl->context = transfer.fctx; 126 if (auto from = weak_from.lock()) {
127 from->impl->previous_fiber->impl->guard.unlock(); 127 ASSERT(from->impl->previous_fiber != nullptr);
128 from->impl->previous_fiber.reset(); 128 from->impl->previous_fiber->impl->context = transfer.fctx;
129 from->impl->previous_fiber->impl->guard.unlock();
130 from->impl->previous_fiber.reset();
131 }
129} 132}
130 133
131std::shared_ptr<Fiber> Fiber::ThreadToFiber() { 134std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
diff --git a/src/common/fiber.h b/src/common/fiber.h
index f7f587f8c..f2a8ff29a 100644
--- a/src/common/fiber.h
+++ b/src/common/fiber.h
@@ -41,7 +41,7 @@ public:
41 41
42 /// Yields control from Fiber 'from' to Fiber 'to' 42 /// Yields control from Fiber 'from' to Fiber 'to'
43 /// Fiber 'from' must be the currently running fiber. 43 /// Fiber 'from' must be the currently running fiber.
44 static void YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to); 44 static void YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to);
45 [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber(); 45 [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
46 46
47 void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param); 47 void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param);
diff --git a/src/common/misc.cpp b/src/common/misc.cpp
index 1d5393597..495385b9e 100644
--- a/src/common/misc.cpp
+++ b/src/common/misc.cpp
@@ -12,27 +12,41 @@
12 12
13#include "common/common_funcs.h" 13#include "common/common_funcs.h"
14 14
15// Generic function to get last error message. 15std::string NativeErrorToString(int e) {
16// Call directly after the command or use the error num.
17// This function might change the error code.
18std::string GetLastErrorMsg() {
19 static constexpr std::size_t buff_size = 255;
20 char err_str[buff_size];
21
22#ifdef _WIN32 16#ifdef _WIN32
23 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(), 17 LPSTR err_str;
24 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_str, buff_size, nullptr); 18
25 return std::string(err_str, buff_size); 19 DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
26#elif defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)) 20 FORMAT_MESSAGE_IGNORE_INSERTS,
21 nullptr, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
22 reinterpret_cast<LPSTR>(&err_str), 1, nullptr);
23 if (!res) {
24 return "(FormatMessageA failed to format error)";
25 }
26 std::string ret(err_str);
27 LocalFree(err_str);
28 return ret;
29#else
30 char err_str[255];
31#if defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600))
27 // Thread safe (GNU-specific) 32 // Thread safe (GNU-specific)
28 const char* str = strerror_r(errno, err_str, buff_size); 33 const char* str = strerror_r(e, err_str, sizeof(err_str));
29 return std::string(str); 34 return std::string(str);
30#else 35#else
31 // Thread safe (XSI-compliant) 36 // Thread safe (XSI-compliant)
32 const int success = strerror_r(errno, err_str, buff_size); 37 int second_err = strerror_r(e, err_str, sizeof(err_str));
33 if (success != 0) { 38 if (second_err != 0) {
34 return {}; 39 return "(strerror_r failed to format error)";
35 } 40 }
36 return std::string(err_str); 41 return std::string(err_str);
42#endif // GLIBC etc.
43#endif // _WIN32
44}
45
46std::string GetLastErrorMsg() {
47#ifdef _WIN32
48 return NativeErrorToString(GetLastError());
49#else
50 return NativeErrorToString(errno);
37#endif 51#endif
38} 52}
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
12namespace Common {
13
14// Implementation of TinyMT (mersenne twister RNG).
15// Like Nintendo, we will use the sample parameters.
16class TinyMT {
17public:
18 static constexpr std::size_t NumStateWords = 4;
19
20 struct State {
21 std::array<u32, NumStateWords> data{};
22 };
23
24private:
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
46private:
47 State state{};
48
49private:
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
101public:
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/core.cpp b/src/core/core.cpp
index de6305e2a..305f56ff1 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -299,28 +299,17 @@ struct System::Impl {
299 gpu_core->WaitIdle(); 299 gpu_core->WaitIdle();
300 } 300 }
301 301
302 // Shutdown emulation session
303 services.reset(); 302 services.reset();
304 service_manager.reset(); 303 service_manager.reset();
305 cheat_engine.reset(); 304 cheat_engine.reset();
306 telemetry_session.reset(); 305 telemetry_session.reset();
307
308 // Close all CPU/threading state
309 cpu_manager.Shutdown(); 306 cpu_manager.Shutdown();
310
311 // Release the Time Manager's resources
312 time_manager.Shutdown(); 307 time_manager.Shutdown();
313
314 // Shutdown kernel and core timing
315 core_timing.Shutdown(); 308 core_timing.Shutdown();
316 kernel.Shutdown();
317
318 // Close app loader
319 app_loader.reset(); 309 app_loader.reset();
320 gpu_core.reset(); 310 gpu_core.reset();
321 perf_stats.reset(); 311 perf_stats.reset();
322 312 kernel.Shutdown();
323 // Clear all applets
324 applet_manager.ClearAll(); 313 applet_manager.ClearAll();
325 314
326 LOG_DEBUG(Core, "Shutdown OK"); 315 LOG_DEBUG(Core, "Shutdown OK");
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 8f04fb8f5..bdb374792 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -148,7 +148,7 @@ void CpuManager::MultiCoreRunSuspendThread() {
148 auto core = kernel.GetCurrentHostThreadID(); 148 auto core = kernel.GetCurrentHostThreadID();
149 auto& scheduler = *kernel.CurrentScheduler(); 149 auto& scheduler = *kernel.CurrentScheduler();
150 Kernel::KThread* current_thread = scheduler.GetCurrentThread(); 150 Kernel::KThread* current_thread = scheduler.GetCurrentThread();
151 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[core].host_context); 151 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
152 ASSERT(scheduler.ContextSwitchPending()); 152 ASSERT(scheduler.ContextSwitchPending());
153 ASSERT(core == kernel.GetCurrentHostThreadID()); 153 ASSERT(core == kernel.GetCurrentHostThreadID());
154 scheduler.RescheduleCurrentCore(); 154 scheduler.RescheduleCurrentCore();
@@ -245,7 +245,7 @@ void CpuManager::SingleCoreRunSuspendThread() {
245 auto core = kernel.GetCurrentHostThreadID(); 245 auto core = kernel.GetCurrentHostThreadID();
246 auto& scheduler = *kernel.CurrentScheduler(); 246 auto& scheduler = *kernel.CurrentScheduler();
247 Kernel::KThread* current_thread = scheduler.GetCurrentThread(); 247 Kernel::KThread* current_thread = scheduler.GetCurrentThread();
248 Common::Fiber::YieldTo(current_thread->GetHostContext(), core_data[0].host_context); 248 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[0].host_context);
249 ASSERT(scheduler.ContextSwitchPending()); 249 ASSERT(scheduler.ContextSwitchPending());
250 ASSERT(core == kernel.GetCurrentHostThreadID()); 250 ASSERT(core == kernel.GetCurrentHostThreadID());
251 scheduler.RescheduleCurrentCore(); 251 scheduler.RescheduleCurrentCore();
@@ -271,7 +271,7 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
271 scheduler.Unload(scheduler.GetCurrentThread()); 271 scheduler.Unload(scheduler.GetCurrentThread());
272 272
273 auto& next_scheduler = kernel.Scheduler(current_core); 273 auto& next_scheduler = kernel.Scheduler(current_core);
274 Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext()); 274 Common::Fiber::YieldTo(current_thread->GetHostContext(), *next_scheduler.ControlContext());
275 } 275 }
276 276
277 // May have changed scheduler 277 // May have changed scheduler
@@ -363,7 +363,7 @@ void CpuManager::RunThread(std::size_t core) {
363 363
364 auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); 364 auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
365 data.is_running = true; 365 data.is_running = true;
366 Common::Fiber::YieldTo(data.host_context, current_thread->GetHostContext()); 366 Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
367 data.is_running = false; 367 data.is_running = false;
368 data.is_paused = true; 368 data.is_paused = true;
369 data.exit_barrier->Wait(); 369 data.exit_barrier->Wait();
diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp
index 6a9734812..cb7506241 100644
--- a/src/core/crypto/aes_util.cpp
+++ b/src/core/crypto/aes_util.cpp
@@ -105,8 +105,6 @@ void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* des
105 } 105 }
106 } 106 }
107 } 107 }
108
109 mbedtls_cipher_finish(context, nullptr, nullptr);
110} 108}
111 109
112template <typename Key, std::size_t KeySize> 110template <typename Key, std::size_t KeySize>
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
13namespace Kernel::Memory { 10namespace Kernel {
14 11
15namespace { 12namespace {
16 13
@@ -28,20 +25,20 @@ enum : u64 {
28}; 25};
29 26
30// clang-format off 27// clang-format off
31constexpr std::array<AddressSpaceInfo, 13> AddressSpaceInfos{{ 28constexpr 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
52using IndexArray = std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)>; 49using IndexArray =
50 std::array<std::size_t, static_cast<std::size_t>(KAddressSpaceInfo::Type::Count)>;
53 51
54constexpr IndexArray AddressSpaceIndices32Bit{ 52constexpr 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
66constexpr bool IsAllowed32BitType(AddressSpaceInfo::Type type) { 64constexpr 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
71constexpr bool IsAllowed36BitType(AddressSpaceInfo::Type type) { 69constexpr 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
76constexpr bool IsAllowed39BitType(AddressSpaceInfo::Type type) { 74constexpr 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
82u64 AddressSpaceInfo::GetAddressSpaceStart(std::size_t width, Type type) { 80u64 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
102std::size_t AddressSpaceInfo::GetAddressSpaceSize(std::size_t width, Type type) { 100std::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
12namespace Kernel::Memory { 9namespace Kernel {
13 10
14struct AddressSpaceInfo final { 11struct 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
16namespace Kernel::Memory { 13namespace Kernel {
17 14
18enum class MemoryState : u32 { 15enum 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};
100DECLARE_ENUM_FLAG_OPERATORS(MemoryState); 97DECLARE_ENUM_FLAG_OPERATORS(KMemoryState);
101 98
102static_assert(static_cast<u32>(MemoryState::Free) == 0x00000000); 99static_assert(static_cast<u32>(KMemoryState::Free) == 0x00000000);
103static_assert(static_cast<u32>(MemoryState::Io) == 0x00002001); 100static_assert(static_cast<u32>(KMemoryState::Io) == 0x00002001);
104static_assert(static_cast<u32>(MemoryState::Static) == 0x00042002); 101static_assert(static_cast<u32>(KMemoryState::Static) == 0x00042002);
105static_assert(static_cast<u32>(MemoryState::Code) == 0x00DC7E03); 102static_assert(static_cast<u32>(KMemoryState::Code) == 0x00DC7E03);
106static_assert(static_cast<u32>(MemoryState::CodeData) == 0x03FEBD04); 103static_assert(static_cast<u32>(KMemoryState::CodeData) == 0x03FEBD04);
107static_assert(static_cast<u32>(MemoryState::Normal) == 0x037EBD05); 104static_assert(static_cast<u32>(KMemoryState::Normal) == 0x037EBD05);
108static_assert(static_cast<u32>(MemoryState::Shared) == 0x00402006); 105static_assert(static_cast<u32>(KMemoryState::Shared) == 0x00402006);
109static_assert(static_cast<u32>(MemoryState::AliasCode) == 0x00DD7E08); 106static_assert(static_cast<u32>(KMemoryState::AliasCode) == 0x00DD7E08);
110static_assert(static_cast<u32>(MemoryState::AliasCodeData) == 0x03FFBD09); 107static_assert(static_cast<u32>(KMemoryState::AliasCodeData) == 0x03FFBD09);
111static_assert(static_cast<u32>(MemoryState::Ipc) == 0x005C3C0A); 108static_assert(static_cast<u32>(KMemoryState::Ipc) == 0x005C3C0A);
112static_assert(static_cast<u32>(MemoryState::Stack) == 0x005C3C0B); 109static_assert(static_cast<u32>(KMemoryState::Stack) == 0x005C3C0B);
113static_assert(static_cast<u32>(MemoryState::ThreadLocal) == 0x0040200C); 110static_assert(static_cast<u32>(KMemoryState::ThreadLocal) == 0x0040200C);
114static_assert(static_cast<u32>(MemoryState::Transferred) == 0x015C3C0D); 111static_assert(static_cast<u32>(KMemoryState::Transferred) == 0x015C3C0D);
115static_assert(static_cast<u32>(MemoryState::SharedTransferred) == 0x005C380E); 112static_assert(static_cast<u32>(KMemoryState::SharedTransferred) == 0x005C380E);
116static_assert(static_cast<u32>(MemoryState::SharedCode) == 0x0040380F); 113static_assert(static_cast<u32>(KMemoryState::SharedCode) == 0x0040380F);
117static_assert(static_cast<u32>(MemoryState::Inaccessible) == 0x00000010); 114static_assert(static_cast<u32>(KMemoryState::Inaccessible) == 0x00000010);
118static_assert(static_cast<u32>(MemoryState::NonSecureIpc) == 0x005C3811); 115static_assert(static_cast<u32>(KMemoryState::NonSecureIpc) == 0x005C3811);
119static_assert(static_cast<u32>(MemoryState::NonDeviceIpc) == 0x004C2812); 116static_assert(static_cast<u32>(KMemoryState::NonDeviceIpc) == 0x004C2812);
120static_assert(static_cast<u32>(MemoryState::Kernel) == 0x00002013); 117static_assert(static_cast<u32>(KMemoryState::Kernel) == 0x00002013);
121static_assert(static_cast<u32>(MemoryState::GeneratedCode) == 0x00402214); 118static_assert(static_cast<u32>(KMemoryState::GeneratedCode) == 0x00402214);
122static_assert(static_cast<u32>(MemoryState::CodeOut) == 0x00402015); 119static_assert(static_cast<u32>(KMemoryState::CodeOut) == 0x00402015);
123 120
124enum class MemoryPermission : u8 { 121enum 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};
138DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission); 135DECLARE_ENUM_FLAG_OPERATORS(KMemoryPermission);
139 136
140enum class MemoryAttribute : u8 { 137enum 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};
155DECLARE_ENUM_FLAG_OPERATORS(MemoryAttribute); 152DECLARE_ENUM_FLAG_OPERATORS(KMemoryAttribute);
156 153
157static_assert((static_cast<u8>(MemoryAttribute::Mask) & 154static_assert((static_cast<u8>(KMemoryAttribute::Mask) &
158 static_cast<u8>(MemoryAttribute::DontCareMask)) == 0); 155 static_cast<u8>(KMemoryAttribute::DontCareMask)) == 0);
159 156
160struct MemoryInfo { 157struct 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
199class MemoryBlock final { 196class KMemoryBlock final {
200 friend class MemoryBlockManager; 197 friend class KMemoryBlockManager;
201 198
202private: 199private:
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
212public: 209public:
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
223public: 220public:
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
273private: 270private:
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};
333static_assert(std::is_trivially_destructible<MemoryBlock>::value); 330static_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
8namespace Kernel::Memory { 8namespace Kernel {
9 9
10MemoryBlockManager::MemoryBlockManager(VAddr start_addr, VAddr end_addr) 10KMemoryBlockManager::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
17MemoryBlockManager::iterator MemoryBlockManager::FindIterator(VAddr addr) { 17KMemoryBlockManager::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
29VAddr MemoryBlockManager::FindFreeArea(VAddr region_start, std::size_t region_num_pages, 29VAddr 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
66void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState prev_state, 66void 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
109void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState state, 109void 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
144void MemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, 144void 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
179void MemoryBlockManager::IterateForRange(VAddr start, VAddr end, IterateFunc&& func) { 179void 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
189void MemoryBlockManager::MergeAdjacent(iterator it, iterator& next_it) { 189void 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
13namespace Kernel::Memory { 13namespace Kernel {
14 14
15class MemoryBlockManager final { 15class KMemoryBlockManager final {
16public: 16public:
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
21public: 21public:
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
10namespace Kernel::Memory { 10namespace Kernel {
11 11
12constexpr std::size_t KernelAslrAlignment = 2 * 1024 * 1024; 12constexpr std::size_t KernelAslrAlignment = 2 * 1024 * 1024;
13constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39; 13constexpr 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
30class MemoryRegion final { 30class KMemoryRegion final {
31 friend class MemoryLayout; 31 friend class KMemoryLayout;
32 32
33public: 33public:
34 constexpr PAddr StartAddress() const { 34 constexpr PAddr StartAddress() const {
@@ -40,29 +40,29 @@ public:
40 } 40 }
41 41
42private: 42private:
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
51class MemoryLayout final { 51class KMemoryLayout final {
52public: 52public:
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
78private: 78private:
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
15namespace Kernel::Memory { 15namespace Kernel {
16 16
17std::size_t MemoryManager::Impl::Initialize(Pool new_pool, u64 start_address, u64 end_address) { 17std::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
44void MemoryManager::InitializeManager(Pool pool, u64 start_address, u64 end_address) { 44void 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
49VAddr MemoryManager::AllocateContinuous(std::size_t num_pages, std::size_t align_pages, Pool pool, 49VAddr 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
82ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pages, Pool pool, 83ResultCode 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
151ResultCode MemoryManager::Free(PageLinkedList& page_list, std::size_t num_pages, Pool pool, 152ResultCode 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
14namespace Kernel::Memory { 16namespace Kernel {
15 17
16class PageLinkedList; 18class KPageLinkedList;
17 19
18class MemoryManager final : NonCopyable { 20class KMemoryManager final : NonCopyable {
19public: 21public:
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
58public:
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
56private: 79private:
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
17namespace Kernel {
18
19class KPageBitmap {
20private:
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
89public:
90 static constexpr std::size_t MaxDepth = 4;
91
92private:
93 std::array<u64*, MaxDepth> bit_storages{};
94 RandomBitGenerator rng{};
95 std::size_t num_bits{};
96 std::size_t used_depths{};
97
98public:
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
217private:
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
255private:
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
267public:
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
12namespace Kernel::Memory { 9namespace Kernel {
13 10
14void PageHeap::Initialize(VAddr address, std::size_t size, std::size_t metadata_size) { 11void 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
35VAddr PageHeap::AllocateBlock(s32 index) { 32VAddr 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
51void PageHeap::FreeBlock(VAddr block, s32 index) { 48void 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
57void PageHeap::Free(VAddr addr, std::size_t num_pages) { 54void 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
107std::size_t PageHeap::CalculateMetadataOverheadSize(std::size_t region_size) { 104std::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
18namespace Kernel {
19
20class KPageHeap final : NonCopyable {
21public:
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
50private:
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
147public:
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
173private:
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
14namespace Kernel::Memory { 14namespace Kernel {
15 15
16class PageLinkedList final { 16class KPageLinkedList final {
17public: 17public:
18 class Node final { 18 class Node final {
19 public: 19 public:
@@ -33,8 +33,8 @@ public:
33 }; 33 };
34 34
35public: 35public:
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
21namespace Kernel::Memory { 22namespace Kernel {
22 23
23namespace { 24namespace {
24 25
@@ -37,14 +38,14 @@ constexpr std::size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceT
37 } 38 }
38} 39}
39 40
40constexpr u64 GetAddressInRange(const MemoryInfo& info, VAddr addr) { 41constexpr 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
47constexpr std::size_t GetSizeInRange(const MemoryInfo& info, VAddr start, VAddr end) { 48constexpr 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
60PageTable::PageTable(Core::System& system) : system{system} {} 61KPageTable::KPageTable(Core::System& system) : system{system} {}
61 62
62ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, 63ResultCode 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
273ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemoryState state, 274ResultCode 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
297ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 298ResultCode 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
334ResultCode PageTable::UnmapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 335ResultCode 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
364void PageTable::MapPhysicalMemory(PageLinkedList& page_linked_list, VAddr start, VAddr end) { 366void 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
396ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) { 398ResultCode 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
444ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) { 446ResultCode 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
481ResultCode PageTable::UnmapMemory(VAddr addr, std::size_t size) { 483ResultCode 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
517ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) { 519ResultCode 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
555ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) { 558ResultCode 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
597ResultCode PageTable::MapPages(VAddr addr, const PageLinkedList& page_linked_list, 600ResultCode 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
619ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, MemoryState state, 622ResultCode 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
641ResultCode PageTable::SetCodeMemoryPermission(VAddr addr, std::size_t size, MemoryPermission perm) { 644ResultCode 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
688MemoryInfo PageTable::QueryInfoImpl(VAddr addr) { 692KMemoryInfo 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
694MemoryInfo PageTable::QueryInfo(VAddr addr) { 698KMemoryInfo 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
703ResultCode PageTable::ReserveTransferMemory(VAddr addr, std::size_t size, MemoryPermission perm) { 707ResultCode 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
721ResultCode PageTable::ResetTransferMemory(VAddr addr, std::size_t size) { 725ResultCode 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
738ResultCode PageTable::SetMemoryAttribute(VAddr addr, std::size_t size, MemoryAttribute mask, 742ResultCode 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
760ResultCode PageTable::SetHeapCapacity(std::size_t new_heap_capacity) { 764ResultCode 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
766ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) { 770ResultVal<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
817ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, 821ResultVal<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
851ResultCode PageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { 855ResultCode 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
874ResultCode PageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) { 878ResultCode 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
897ResultCode PageTable::InitializeMemoryLayout(VAddr start, VAddr end) { 901ResultCode 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
903bool PageTable::IsRegionMapped(VAddr address, u64 size) { 907bool 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
910bool PageTable::IsRegionContiguous(VAddr addr, u64 size) const { 915bool 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
921void PageTable::AddRegionToPages(VAddr start, std::size_t num_pages, 926void 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
934VAddr PageTable::AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, 939VAddr 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
943ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, const PageLinkedList& page_group, 948ResultCode 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
968ResultCode PageTable::Operate(VAddr addr, std::size_t num_pages, MemoryPermission perm, 973ResultCode 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
995constexpr VAddr PageTable::GetRegionAddress(MemoryState state) const { 1000constexpr 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
1030constexpr std::size_t PageTable::GetRegionSize(MemoryState state) const { 1035constexpr 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
1065constexpr bool PageTable::CanContain(VAddr addr, std::size_t size, MemoryState state) const { 1070constexpr 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
1107constexpr ResultCode PageTable::CheckMemoryState(const MemoryInfo& info, MemoryState state_mask, 1112constexpr 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
1125ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission* out_perm, 1131ResultCode 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
17namespace Core { 17namespace Core {
18class System; 18class System;
19} 19}
20 20
21namespace Kernel::Memory { 21namespace Kernel {
22 22
23class MemoryBlockManager; 23class KMemoryBlockManager;
24 24
25class PageTable final : NonCopyable { 25class KPageTable final : NonCopyable {
26public: 26public:
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
117public: 119public:
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
218private: 220private:
@@ -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/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index bb5f43b53..e7de48476 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -734,7 +734,7 @@ void KScheduler::ScheduleImpl() {
734 } 734 }
735 guard.unlock(); 735 guard.unlock();
736 736
737 Common::Fiber::YieldTo(*old_context, switch_fiber); 737 Common::Fiber::YieldTo(*old_context, *switch_fiber);
738 /// When a thread wakes up, the scheduler may have changed to other in another core. 738 /// When a thread wakes up, the scheduler may have changed to other in another core.
739 auto& next_scheduler = *system.Kernel().CurrentScheduler(); 739 auto& next_scheduler = *system.Kernel().CurrentScheduler();
740 next_scheduler.SwitchContextStep2(); 740 next_scheduler.SwitchContextStep2();
@@ -769,13 +769,8 @@ void KScheduler::SwitchToCurrent() {
769 break; 769 break;
770 } 770 }
771 } 771 }
772 std::shared_ptr<Common::Fiber>* next_context; 772 auto thread = next_thread ? next_thread : idle_thread;
773 if (next_thread != nullptr) { 773 Common::Fiber::YieldTo(switch_fiber, *thread->GetHostContext());
774 next_context = &next_thread->GetHostContext();
775 } else {
776 next_context = &idle_thread->GetHostContext();
777 }
778 Common::Fiber::YieldTo(switch_fiber, *next_context);
779 } while (!is_switch_pending()); 774 } while (!is_switch_pending());
780 } 775 }
781} 776}
@@ -800,9 +795,9 @@ void KScheduler::Initialize() {
800 std::string name = "Idle Thread Id:" + std::to_string(core_id); 795 std::string name = "Idle Thread Id:" + std::to_string(core_id);
801 std::function<void(void*)> init_func = Core::CpuManager::GetIdleThreadStartFunc(); 796 std::function<void(void*)> init_func = Core::CpuManager::GetIdleThreadStartFunc();
802 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); 797 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
803 auto thread_res = KThread::Create(system, ThreadType::Main, name, 0, 798 auto thread_res = KThread::CreateThread(
804 KThread::IdleThreadPriority, 0, static_cast<u32>(core_id), 0, 799 system, ThreadType::Main, name, 0, KThread::IdleThreadPriority, 0,
805 nullptr, std::move(init_func), init_func_parameter); 800 static_cast<u32>(core_id), 0, nullptr, std::move(init_func), init_func_parameter);
806 idle_thread = thread_res.Unwrap().get(); 801 idle_thread = thread_res.Unwrap().get();
807} 802}
808 803
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
12namespace Kernel { 12namespace Kernel {
13 13
14SharedMemory::SharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory) 14KSharedMemory::KSharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory)
15 : Object{kernel}, device_memory{device_memory} {} 15 : Object{kernel}, device_memory{device_memory} {}
16 16
17SharedMemory::~SharedMemory() { 17KSharedMemory::~KSharedMemory() {
18 kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); 18 kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size);
19} 19}
20 20
21std::shared_ptr<SharedMemory> SharedMemory::Create( 21std::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
47ResultCode SharedMemory::Map(Process& target_process, VAddr address, std::size_t size, 46ResultCode 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
20class KernelCore; 20class KernelCore;
21 21
22class SharedMemory final : public Object { 22class KSharedMemory final : public Object {
23public: 23public:
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:
76private: 76private:
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
15namespace Kernel::Memory { 12namespace Kernel {
16 13
17namespace impl { 14namespace impl {
18 15
19class SlabHeapImpl final : NonCopyable { 16class KSlabHeapImpl final : NonCopyable {
20public: 17public:
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
68class SlabHeapBase : NonCopyable { 65class KSlabHeapBase : NonCopyable {
69public: 66public:
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
128private: 125private:
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
137template <typename T> 134template <typename T>
138class SlabHeap final : public SlabHeapBase { 135class KSlabHeap final : public KSlabHeapBase {
139public: 136public:
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
21namespace {
22
23void 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
35namespace Kernel {
36
37void KSpinLock::Lock() {
38 while (lck.test_and_set(std::memory_order_acquire)) {
39 ThreadPause();
40 }
41}
42
43void KSpinLock::Unlock() {
44 lck.clear(std::memory_order_release);
45}
46
47bool 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
11namespace Kernel {
12
13class KSpinLock {
14public:
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
27private:
28 std::atomic_flag lck = ATOMIC_FLAG_INIT;
29};
30
31using 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
9namespace Kernel {
8 10
9namespace Kernel::Memory::SystemControl {
10namespace { 11namespace {
11template <typename F> 12template <typename F>
12u64 GenerateUniformRange(u64 min, u64 max, F f) { 13u64 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
28u64 GenerateRandomU64ForInit() { 29} // Anonymous namespace
30
31u64 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
36u64 GenerateRandomRange(u64 min, u64 max) { 38u64 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
9namespace Kernel {
10
11class KSystemControl {
12public:
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..e0f53287c 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);
@@ -995,22 +995,11 @@ std::shared_ptr<Common::Fiber>& KThread::GetHostContext() {
995 return host_context; 995 return host_context;
996} 996}
997 997
998ResultVal<std::shared_ptr<KThread>> KThread::Create(Core::System& system, ThreadType type_flags, 998ResultVal<std::shared_ptr<KThread>> KThread::CreateThread(Core::System& system,
999 std::string name, VAddr entry_point, 999 ThreadType type_flags, std::string name,
1000 u32 priority, u64 arg, s32 processor_id, 1000 VAddr entry_point, u32 priority, u64 arg,
1001 VAddr stack_top, Process* owner_process) { 1001 s32 processor_id, VAddr stack_top,
1002 std::function<void(void*)> init_func = Core::CpuManager::GetGuestThreadStartFunc(); 1002 Process* owner_process) {
1003 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
1004 return Create(system, type_flags, name, entry_point, priority, arg, processor_id, stack_top,
1005 owner_process, std::move(init_func), init_func_parameter);
1006}
1007
1008ResultVal<std::shared_ptr<KThread>> KThread::Create(Core::System& system, ThreadType type_flags,
1009 std::string name, VAddr entry_point,
1010 u32 priority, u64 arg, s32 processor_id,
1011 VAddr stack_top, Process* owner_process,
1012 std::function<void(void*)>&& thread_start_func,
1013 void* thread_start_parameter) {
1014 auto& kernel = system.Kernel(); 1003 auto& kernel = system.Kernel();
1015 1004
1016 std::shared_ptr<KThread> thread = std::make_shared<KThread>(kernel); 1005 std::shared_ptr<KThread> thread = std::make_shared<KThread>(kernel);
@@ -1027,12 +1016,35 @@ ResultVal<std::shared_ptr<KThread>> KThread::Create(Core::System& system, Thread
1027 auto& scheduler = kernel.GlobalSchedulerContext(); 1016 auto& scheduler = kernel.GlobalSchedulerContext();
1028 scheduler.AddThread(thread); 1017 scheduler.AddThread(thread);
1029 1018
1030 thread->host_context =
1031 std::make_shared<Common::Fiber>(std::move(thread_start_func), thread_start_parameter);
1032
1033 return MakeResult<std::shared_ptr<KThread>>(std::move(thread)); 1019 return MakeResult<std::shared_ptr<KThread>>(std::move(thread));
1034} 1020}
1035 1021
1022ResultVal<std::shared_ptr<KThread>> KThread::CreateThread(
1023 Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, u32 priority,
1024 u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process,
1025 std::function<void(void*)>&& thread_start_func, void* thread_start_parameter) {
1026 auto thread_result = CreateThread(system, type_flags, name, entry_point, priority, arg,
1027 processor_id, stack_top, owner_process);
1028
1029 if (thread_result.Succeeded()) {
1030 (*thread_result)->host_context =
1031 std::make_shared<Common::Fiber>(std::move(thread_start_func), thread_start_parameter);
1032 }
1033
1034 return thread_result;
1035}
1036
1037ResultVal<std::shared_ptr<KThread>> KThread::CreateUserThread(
1038 Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, u32 priority,
1039 u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process) {
1040 std::function<void(void*)> init_func = Core::CpuManager::GetGuestThreadStartFunc();
1041
1042 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
1043
1044 return CreateThread(system, type_flags, name, entry_point, priority, arg, processor_id,
1045 stack_top, owner_process, std::move(init_func), init_func_parameter);
1046}
1047
1036KThread* GetCurrentThreadPointer(KernelCore& kernel) { 1048KThread* GetCurrentThreadPointer(KernelCore& kernel) {
1037 return kernel.GetCurrentEmuThread(); 1049 return kernel.GetCurrentEmuThread();
1038} 1050}
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index c8ac656a4..1c19b23dc 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -116,7 +116,7 @@ public:
116 using WaiterList = boost::intrusive::list<KThread>; 116 using WaiterList = boost::intrusive::list<KThread>;
117 117
118 /** 118 /**
119 * Creates and returns a new thread. The new thread is immediately scheduled 119 * Creates and returns a new thread.
120 * @param system The instance of the whole system 120 * @param system The instance of the whole system
121 * @param name The friendly name desired for the thread 121 * @param name The friendly name desired for the thread
122 * @param entry_point The address at which the thread should start execution 122 * @param entry_point The address at which the thread should start execution
@@ -127,12 +127,12 @@ public:
127 * @param owner_process The parent process for the thread, if null, it's a kernel thread 127 * @param owner_process The parent process for the thread, if null, it's a kernel thread
128 * @return A shared pointer to the newly created thread 128 * @return A shared pointer to the newly created thread
129 */ 129 */
130 [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> Create( 130 [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> CreateThread(
131 Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, 131 Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point,
132 u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process); 132 u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process);
133 133
134 /** 134 /**
135 * Creates and returns a new thread. The new thread is immediately scheduled 135 * Creates and returns a new thread, with a specified entry point.
136 * @param system The instance of the whole system 136 * @param system The instance of the whole system
137 * @param name The friendly name desired for the thread 137 * @param name The friendly name desired for the thread
138 * @param entry_point The address at which the thread should start execution 138 * @param entry_point The address at which the thread should start execution
@@ -145,11 +145,27 @@ public:
145 * @param thread_start_parameter The parameter which will passed to host context on init 145 * @param thread_start_parameter The parameter which will passed to host context on init
146 * @return A shared pointer to the newly created thread 146 * @return A shared pointer to the newly created thread
147 */ 147 */
148 [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> Create( 148 [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> CreateThread(
149 Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point, 149 Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point,
150 u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process, 150 u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process,
151 std::function<void(void*)>&& thread_start_func, void* thread_start_parameter); 151 std::function<void(void*)>&& thread_start_func, void* thread_start_parameter);
152 152
153 /**
154 * Creates and returns a new thread for the emulated "user" process.
155 * @param system The instance of the whole system
156 * @param name The friendly name desired for the thread
157 * @param entry_point The address at which the thread should start execution
158 * @param priority The thread's priority
159 * @param arg User data to pass to the thread
160 * @param processor_id The ID(s) of the processors on which the thread is desired to be run
161 * @param stack_top The address of the thread's stack top
162 * @param owner_process The parent process for the thread, if null, it's a kernel thread
163 * @return A shared pointer to the newly created thread
164 */
165 [[nodiscard]] static ResultVal<std::shared_ptr<KThread>> CreateUserThread(
166 Core::System& system, ThreadType type_flags, std::string name, VAddr entry_point,
167 u32 priority, u64 arg, s32 processor_id, VAddr stack_top, Process* owner_process);
168
153 [[nodiscard]] std::string GetName() const override { 169 [[nodiscard]] std::string GetName() const override {
154 return name; 170 return name;
155 } 171 }
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 39c5182c5..780008b08 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"
@@ -181,9 +181,9 @@ struct KernelCore::Impl {
181 std::string name = "Suspend Thread Id:" + std::to_string(i); 181 std::string name = "Suspend Thread Id:" + std::to_string(i);
182 std::function<void(void*)> init_func = Core::CpuManager::GetSuspendThreadStartFunc(); 182 std::function<void(void*)> init_func = Core::CpuManager::GetSuspendThreadStartFunc();
183 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); 183 void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
184 auto thread_res = KThread::Create(system, ThreadType::HighPriority, std::move(name), 0, 184 auto thread_res = KThread::CreateThread(
185 0, 0, static_cast<u32>(i), 0, nullptr, 185 system, ThreadType::HighPriority, std::move(name), 0, 0, 0, static_cast<u32>(i), 0,
186 std::move(init_func), init_func_parameter); 186 nullptr, std::move(init_func), init_func_parameter);
187 187
188 suspend_threads[i] = std::move(thread_res).Unwrap(); 188 suspend_threads[i] = std::move(thread_res).Unwrap();
189 } 189 }
@@ -221,10 +221,9 @@ struct KernelCore::Impl {
221 // Gets the dummy KThread for the caller, allocating a new one if this is the first time 221 // Gets the dummy KThread for the caller, allocating a new one if this is the first time
222 KThread* GetHostDummyThread() { 222 KThread* GetHostDummyThread() {
223 const thread_local auto thread = 223 const thread_local auto thread =
224 KThread::Create( 224 KThread::CreateThread(
225 system, ThreadType::Main, fmt::format("DummyThread:{}", GetHostThreadId()), 0, 225 system, ThreadType::Main, fmt::format("DummyThread:{}", GetHostThreadId()), 0,
226 KThread::DefaultThreadPriority, 0, static_cast<u32>(3), 0, nullptr, 226 KThread::DefaultThreadPriority, 0, static_cast<u32>(3), 0, nullptr)
227 []([[maybe_unused]] void* arg) { UNREACHABLE(); }, nullptr)
228 .Unwrap(); 227 .Unwrap();
229 return thread.get(); 228 return thread.get();
230 } 229 }
@@ -271,7 +270,7 @@ struct KernelCore::Impl {
271 270
272 void InitializeMemoryLayout() { 271 void InitializeMemoryLayout() {
273 // Initialize memory layout 272 // Initialize memory layout
274 constexpr Memory::MemoryLayout layout{Memory::MemoryLayout::GetDefaultLayout()}; 273 constexpr KMemoryLayout layout{KMemoryLayout::GetDefaultLayout()};
275 constexpr std::size_t hid_size{0x40000}; 274 constexpr std::size_t hid_size{0x40000};
276 constexpr std::size_t font_size{0x1100000}; 275 constexpr std::size_t font_size{0x1100000};
277 constexpr std::size_t irs_size{0x8000}; 276 constexpr std::size_t irs_size{0x8000};
@@ -282,36 +281,36 @@ struct KernelCore::Impl {
282 constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size}; 281 constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size};
283 282
284 // Initialize memory manager 283 // Initialize memory manager
285 memory_manager = std::make_unique<Memory::MemoryManager>(); 284 memory_manager = std::make_unique<KMemoryManager>();
286 memory_manager->InitializeManager(Memory::MemoryManager::Pool::Application, 285 memory_manager->InitializeManager(KMemoryManager::Pool::Application,
287 layout.Application().StartAddress(), 286 layout.Application().StartAddress(),
288 layout.Application().EndAddress()); 287 layout.Application().EndAddress());
289 memory_manager->InitializeManager(Memory::MemoryManager::Pool::Applet, 288 memory_manager->InitializeManager(KMemoryManager::Pool::Applet,
290 layout.Applet().StartAddress(), 289 layout.Applet().StartAddress(),
291 layout.Applet().EndAddress()); 290 layout.Applet().EndAddress());
292 memory_manager->InitializeManager(Memory::MemoryManager::Pool::System, 291 memory_manager->InitializeManager(KMemoryManager::Pool::System,
293 layout.System().StartAddress(), 292 layout.System().StartAddress(),
294 layout.System().EndAddress()); 293 layout.System().EndAddress());
295 294
296 hid_shared_mem = Kernel::SharedMemory::Create( 295 hid_shared_mem = Kernel::KSharedMemory::Create(
297 system.Kernel(), system.DeviceMemory(), nullptr, 296 system.Kernel(), system.DeviceMemory(), nullptr, {hid_addr, hid_size / PageSize},
298 {hid_addr, hid_size / Memory::PageSize}, Memory::MemoryPermission::None, 297 KMemoryPermission::None, KMemoryPermission::Read, hid_addr, hid_size,
299 Memory::MemoryPermission::Read, hid_addr, hid_size, "HID:SharedMemory"); 298 "HID:SharedMemory");
300 font_shared_mem = Kernel::SharedMemory::Create( 299 font_shared_mem = Kernel::KSharedMemory::Create(
301 system.Kernel(), system.DeviceMemory(), nullptr, 300 system.Kernel(), system.DeviceMemory(), nullptr, {font_pa, font_size / PageSize},
302 {font_pa, font_size / Memory::PageSize}, Memory::MemoryPermission::None, 301 KMemoryPermission::None, KMemoryPermission::Read, font_pa, font_size,
303 Memory::MemoryPermission::Read, font_pa, font_size, "Font:SharedMemory"); 302 "Font:SharedMemory");
304 irs_shared_mem = Kernel::SharedMemory::Create( 303 irs_shared_mem = Kernel::KSharedMemory::Create(
305 system.Kernel(), system.DeviceMemory(), nullptr, 304 system.Kernel(), system.DeviceMemory(), nullptr, {irs_addr, irs_size / PageSize},
306 {irs_addr, irs_size / Memory::PageSize}, Memory::MemoryPermission::None, 305 KMemoryPermission::None, KMemoryPermission::Read, irs_addr, irs_size,
307 Memory::MemoryPermission::Read, irs_addr, irs_size, "IRS:SharedMemory"); 306 "IRS:SharedMemory");
308 time_shared_mem = Kernel::SharedMemory::Create( 307 time_shared_mem = Kernel::KSharedMemory::Create(
309 system.Kernel(), system.DeviceMemory(), nullptr, 308 system.Kernel(), system.DeviceMemory(), nullptr, {time_addr, time_size / PageSize},
310 {time_addr, time_size / Memory::PageSize}, Memory::MemoryPermission::None, 309 KMemoryPermission::None, KMemoryPermission::Read, time_addr, time_size,
311 Memory::MemoryPermission::Read, time_addr, time_size, "Time:SharedMemory"); 310 "Time:SharedMemory");
312 311
313 // Allocate slab heaps 312 // Allocate slab heaps
314 user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>(); 313 user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
315 314
316 constexpr u64 user_slab_heap_size{0x1ef000}; 315 constexpr u64 user_slab_heap_size{0x1ef000};
317 // Reserve slab heaps 316 // Reserve slab heaps
@@ -353,14 +352,14 @@ struct KernelCore::Impl {
353 std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES}; 352 std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES};
354 353
355 // Kernel memory management 354 // Kernel memory management
356 std::unique_ptr<Memory::MemoryManager> memory_manager; 355 std::unique_ptr<KMemoryManager> memory_manager;
357 std::unique_ptr<Memory::SlabHeap<Memory::Page>> user_slab_heap_pages; 356 std::unique_ptr<KSlabHeap<Page>> user_slab_heap_pages;
358 357
359 // Shared memory for services 358 // Shared memory for services
360 std::shared_ptr<Kernel::SharedMemory> hid_shared_mem; 359 std::shared_ptr<Kernel::KSharedMemory> hid_shared_mem;
361 std::shared_ptr<Kernel::SharedMemory> font_shared_mem; 360 std::shared_ptr<Kernel::KSharedMemory> font_shared_mem;
362 std::shared_ptr<Kernel::SharedMemory> irs_shared_mem; 361 std::shared_ptr<Kernel::KSharedMemory> irs_shared_mem;
363 std::shared_ptr<Kernel::SharedMemory> time_shared_mem; 362 std::shared_ptr<Kernel::KSharedMemory> time_shared_mem;
364 363
365 // Threads used for services 364 // Threads used for services
366 std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads; 365 std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
@@ -578,51 +577,51 @@ KThread* KernelCore::GetCurrentEmuThread() const {
578 return impl->GetCurrentEmuThread(); 577 return impl->GetCurrentEmuThread();
579} 578}
580 579
581Memory::MemoryManager& KernelCore::MemoryManager() { 580KMemoryManager& KernelCore::MemoryManager() {
582 return *impl->memory_manager; 581 return *impl->memory_manager;
583} 582}
584 583
585const Memory::MemoryManager& KernelCore::MemoryManager() const { 584const KMemoryManager& KernelCore::MemoryManager() const {
586 return *impl->memory_manager; 585 return *impl->memory_manager;
587} 586}
588 587
589Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() { 588KSlabHeap<Page>& KernelCore::GetUserSlabHeapPages() {
590 return *impl->user_slab_heap_pages; 589 return *impl->user_slab_heap_pages;
591} 590}
592 591
593const Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() const { 592const KSlabHeap<Page>& KernelCore::GetUserSlabHeapPages() const {
594 return *impl->user_slab_heap_pages; 593 return *impl->user_slab_heap_pages;
595} 594}
596 595
597Kernel::SharedMemory& KernelCore::GetHidSharedMem() { 596Kernel::KSharedMemory& KernelCore::GetHidSharedMem() {
598 return *impl->hid_shared_mem; 597 return *impl->hid_shared_mem;
599} 598}
600 599
601const Kernel::SharedMemory& KernelCore::GetHidSharedMem() const { 600const Kernel::KSharedMemory& KernelCore::GetHidSharedMem() const {
602 return *impl->hid_shared_mem; 601 return *impl->hid_shared_mem;
603} 602}
604 603
605Kernel::SharedMemory& KernelCore::GetFontSharedMem() { 604Kernel::KSharedMemory& KernelCore::GetFontSharedMem() {
606 return *impl->font_shared_mem; 605 return *impl->font_shared_mem;
607} 606}
608 607
609const Kernel::SharedMemory& KernelCore::GetFontSharedMem() const { 608const Kernel::KSharedMemory& KernelCore::GetFontSharedMem() const {
610 return *impl->font_shared_mem; 609 return *impl->font_shared_mem;
611} 610}
612 611
613Kernel::SharedMemory& KernelCore::GetIrsSharedMem() { 612Kernel::KSharedMemory& KernelCore::GetIrsSharedMem() {
614 return *impl->irs_shared_mem; 613 return *impl->irs_shared_mem;
615} 614}
616 615
617const Kernel::SharedMemory& KernelCore::GetIrsSharedMem() const { 616const Kernel::KSharedMemory& KernelCore::GetIrsSharedMem() const {
618 return *impl->irs_shared_mem; 617 return *impl->irs_shared_mem;
619} 618}
620 619
621Kernel::SharedMemory& KernelCore::GetTimeSharedMem() { 620Kernel::KSharedMemory& KernelCore::GetTimeSharedMem() {
622 return *impl->time_shared_mem; 621 return *impl->time_shared_mem;
623} 622}
624 623
625const Kernel::SharedMemory& KernelCore::GetTimeSharedMem() const { 624const Kernel::KSharedMemory& KernelCore::GetTimeSharedMem() const {
626 return *impl->time_shared_mem; 625 return *impl->time_shared_mem;
627} 626}
628 627
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
17namespace Core { 17namespace Core {
@@ -27,25 +27,23 @@ struct EventType;
27 27
28namespace Kernel { 28namespace Kernel {
29 29
30namespace Memory {
31class MemoryManager;
32template <typename T>
33class SlabHeap;
34} // namespace Memory
35
36class ClientPort; 30class ClientPort;
37class GlobalSchedulerContext; 31class GlobalSchedulerContext;
38class HandleTable; 32class HandleTable;
39class PhysicalCore; 33class KMemoryManager;
40class Process;
41class KResourceLimit; 34class KResourceLimit;
42class KScheduler; 35class KScheduler;
43class SharedMemory; 36class KSharedMemory;
37class KThread;
38class PhysicalCore;
39class Process;
44class ServiceThread; 40class ServiceThread;
45class Synchronization; 41class Synchronization;
46class KThread;
47class TimeManager; 42class TimeManager;
48 43
44template <typename T>
45class KSlabHeap;
46
49using EmuThreadHandle = uintptr_t; 47using EmuThreadHandle = uintptr_t;
50constexpr EmuThreadHandle EmuThreadHandleInvalid{}; 48constexpr EmuThreadHandle EmuThreadHandleInvalid{};
51constexpr EmuThreadHandle EmuThreadHandleReserved{1ULL << 63}; 49constexpr 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
20namespace Kernel::Memory {
21
22class PageHeap final : NonCopyable {
23public:
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
52private:
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
324public:
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
350private:
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
9namespace Kernel::Memory::SystemControl {
10
11u64 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
11namespace Kernel::Memory { 11namespace Kernel {
12 12
13constexpr std::size_t PageBits{12}; 13constexpr std::size_t PageBits{12};
14constexpr std::size_t PageSize{1 << PageBits}; 14constexpr std::size_t PageSize{1 << PageBits};
15 15
16using Page = std::array<u8, PageSize>; 16using 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..9d5956ead 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"
@@ -40,8 +40,9 @@ namespace {
40void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) { 40void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) {
41 const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); 41 const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart();
42 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1)); 42 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1));
43 auto thread_res = KThread::Create(system, ThreadType::User, "main", entry_point, priority, 0, 43 auto thread_res =
44 owner_process.GetIdealCoreId(), stack_top, &owner_process); 44 KThread::CreateUserThread(system, ThreadType::User, "main", entry_point, priority, 0,
45 owner_process.GetIdealCoreId(), stack_top, &owner_process);
45 46
46 std::shared_ptr<KThread> thread = std::move(thread_res).Unwrap(); 47 std::shared_ptr<KThread> thread = std::move(thread_res).Unwrap();
47 48
@@ -274,7 +275,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
274 // Set initial resource limits 275 // Set initial resource limits
275 resource_limit->SetLimitValue( 276 resource_limit->SetLimitValue(
276 LimitableResource::PhysicalMemory, 277 LimitableResource::PhysicalMemory,
277 kernel.MemoryManager().GetSize(Memory::MemoryManager::Pool::Application)); 278 kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
278 KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, 279 KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory,
279 code_size + system_resource_size); 280 code_size + system_resource_size);
280 if (!memory_reservation.Succeeded()) { 281 if (!memory_reservation.Succeeded()) {
@@ -285,15 +286,15 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
285 // Initialize proces address space 286 // Initialize proces address space
286 if (const ResultCode result{ 287 if (const ResultCode result{
287 page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false, 0x8000000, 288 page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false, 0x8000000,
288 code_size, Memory::MemoryManager::Pool::Application)}; 289 code_size, KMemoryManager::Pool::Application)};
289 result.IsError()) { 290 result.IsError()) {
290 return result; 291 return result;
291 } 292 }
292 293
293 // Map process code region 294 // Map process code region
294 if (const ResultCode result{page_table->MapProcessCode( 295 if (const ResultCode result{page_table->MapProcessCode(page_table->GetCodeRegionStart(),
295 page_table->GetCodeRegionStart(), code_size / Memory::PageSize, 296 code_size / PageSize, KMemoryState::Code,
296 Memory::MemoryState::Code, Memory::MemoryPermission::None)}; 297 KMemoryPermission::None)};
297 result.IsError()) { 298 result.IsError()) {
298 return result; 299 return result;
299 } 300 }
@@ -323,6 +324,11 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
323 UNREACHABLE(); 324 UNREACHABLE();
324 } 325 }
325 326
327 // Set initial resource limits
328 resource_limit->SetLimitValue(
329 LimitableResource::PhysicalMemory,
330 kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
331
326 resource_limit->SetLimitValue(LimitableResource::Threads, 608); 332 resource_limit->SetLimitValue(LimitableResource::Threads, 608);
327 resource_limit->SetLimitValue(LimitableResource::Events, 700); 333 resource_limit->SetLimitValue(LimitableResource::Events, 700);
328 resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128); 334 resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128);
@@ -400,22 +406,22 @@ VAddr Process::CreateTLSRegion() {
400 return *tls_page_iter->ReserveSlot(); 406 return *tls_page_iter->ReserveSlot();
401 } 407 }
402 408
403 Memory::Page* const tls_page_ptr{kernel.GetUserSlabHeapPages().Allocate()}; 409 Page* const tls_page_ptr{kernel.GetUserSlabHeapPages().Allocate()};
404 ASSERT(tls_page_ptr); 410 ASSERT(tls_page_ptr);
405 411
406 const VAddr start{page_table->GetKernelMapRegionStart()}; 412 const VAddr start{page_table->GetKernelMapRegionStart()};
407 const VAddr size{page_table->GetKernelMapRegionEnd() - start}; 413 const VAddr size{page_table->GetKernelMapRegionEnd() - start};
408 const PAddr tls_map_addr{system.DeviceMemory().GetPhysicalAddr(tls_page_ptr)}; 414 const PAddr tls_map_addr{system.DeviceMemory().GetPhysicalAddr(tls_page_ptr)};
409 const VAddr tls_page_addr{ 415 const VAddr tls_page_addr{page_table
410 page_table 416 ->AllocateAndMapMemory(1, PageSize, true, start, size / PageSize,
411 ->AllocateAndMapMemory(1, Memory::PageSize, true, start, size / Memory::PageSize, 417 KMemoryState::ThreadLocal,
412 Memory::MemoryState::ThreadLocal, 418 KMemoryPermission::ReadAndWrite,
413 Memory::MemoryPermission::ReadAndWrite, tls_map_addr) 419 tls_map_addr)
414 .ValueOr(0)}; 420 .ValueOr(0)};
415 421
416 ASSERT(tls_page_addr); 422 ASSERT(tls_page_addr);
417 423
418 std::memset(tls_page_ptr, 0, Memory::PageSize); 424 std::memset(tls_page_ptr, 0, PageSize);
419 tls_pages.emplace_back(tls_page_addr); 425 tls_pages.emplace_back(tls_page_addr);
420 426
421 const auto reserve_result{tls_pages.back().ReserveSlot()}; 427 const auto reserve_result{tls_pages.back().ReserveSlot()};
@@ -442,15 +448,15 @@ void Process::FreeTLSRegion(VAddr tls_address) {
442void Process::LoadModule(CodeSet code_set, VAddr base_addr) { 448void Process::LoadModule(CodeSet code_set, VAddr base_addr) {
443 std::lock_guard lock{HLE::g_hle_lock}; 449 std::lock_guard lock{HLE::g_hle_lock};
444 const auto ReprotectSegment = [&](const CodeSet::Segment& segment, 450 const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
445 Memory::MemoryPermission permission) { 451 KMemoryPermission permission) {
446 page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission); 452 page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission);
447 }; 453 };
448 454
449 system.Memory().WriteBlock(*this, base_addr, code_set.memory.data(), code_set.memory.size()); 455 system.Memory().WriteBlock(*this, base_addr, code_set.memory.data(), code_set.memory.size());
450 456
451 ReprotectSegment(code_set.CodeSegment(), Memory::MemoryPermission::ReadAndExecute); 457 ReprotectSegment(code_set.CodeSegment(), KMemoryPermission::ReadAndExecute);
452 ReprotectSegment(code_set.RODataSegment(), Memory::MemoryPermission::Read); 458 ReprotectSegment(code_set.RODataSegment(), KMemoryPermission::Read);
453 ReprotectSegment(code_set.DataSegment(), Memory::MemoryPermission::ReadAndWrite); 459 ReprotectSegment(code_set.DataSegment(), KMemoryPermission::ReadAndWrite);
454} 460}
455 461
456bool Process::IsSignaled() const { 462bool Process::IsSignaled() const {
@@ -459,9 +465,9 @@ bool Process::IsSignaled() const {
459} 465}
460 466
461Process::Process(Core::System& system) 467Process::Process(Core::System& system)
462 : KSynchronizationObject{system.Kernel()}, 468 : KSynchronizationObject{system.Kernel()}, page_table{std::make_unique<KPageTable>(system)},
463 page_table{std::make_unique<Memory::PageTable>(system)}, handle_table{system.Kernel()}, 469 handle_table{system.Kernel()}, address_arbiter{system}, condition_var{system},
464 address_arbiter{system}, condition_var{system}, state_lock{system.Kernel()}, system{system} {} 470 state_lock{system.Kernel()}, system{system} {}
465 471
466Process::~Process() = default; 472Process::~Process() = default;
467 473
@@ -479,16 +485,15 @@ ResultCode Process::AllocateMainThreadStack(std::size_t stack_size) {
479 ASSERT(stack_size); 485 ASSERT(stack_size);
480 486
481 // The kernel always ensures that the given stack size is page aligned. 487 // The kernel always ensures that the given stack size is page aligned.
482 main_thread_stack_size = Common::AlignUp(stack_size, Memory::PageSize); 488 main_thread_stack_size = Common::AlignUp(stack_size, PageSize);
483 489
484 const VAddr start{page_table->GetStackRegionStart()}; 490 const VAddr start{page_table->GetStackRegionStart()};
485 const std::size_t size{page_table->GetStackRegionEnd() - start}; 491 const std::size_t size{page_table->GetStackRegionEnd() - start};
486 492
487 CASCADE_RESULT(main_thread_stack_top, 493 CASCADE_RESULT(main_thread_stack_top,
488 page_table->AllocateAndMapMemory( 494 page_table->AllocateAndMapMemory(
489 main_thread_stack_size / Memory::PageSize, Memory::PageSize, false, start, 495 main_thread_stack_size / PageSize, PageSize, false, start, size / PageSize,
490 size / Memory::PageSize, Memory::MemoryState::Stack, 496 KMemoryState::Stack, KMemoryPermission::ReadAndWrite));
491 Memory::MemoryPermission::ReadAndWrite));
492 497
493 main_thread_stack_top += main_thread_stack_size; 498 main_thread_stack_top += main_thread_stack_size;
494 499
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;
29namespace Kernel { 29namespace Kernel {
30 30
31class KernelCore; 31class KernelCore;
32class KPageTable;
32class KResourceLimit; 33class KResourceLimit;
33class KThread; 34class KThread;
34class TLSPage; 35class TLSPage;
35 36
36struct CodeSet; 37struct CodeSet;
37 38
38namespace Memory {
39class PageTable;
40}
41
42enum class MemoryRegion : u16 { 39enum 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
70ResultCode ProcessCapabilities::InitializeForKernelProcess(const u32* capabilities, 70ResultCode 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
83ResultCode ProcessCapabilities::InitializeForUserProcess(const u32* capabilities, 83ResultCode 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
109ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities, 109ResultCode 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
157ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, 157ResultCode 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
295ResultCode ProcessCapabilities::HandleMapPhysicalFlags(u32 flags, u32 size_flags, 295ResultCode 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
301ResultCode ProcessCapabilities::HandleMapIOFlags(u32 flags, Memory::PageTable& page_table) { 301ResultCode 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
13namespace Kernel { 13namespace Kernel {
14 14
15namespace Memory { 15class KPageTable;
16class 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..326d3b9ec 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.
70ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr dst_addr, 70ResultCode 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
248static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, 248static 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
1280static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr, 1279static ResultCode MapSharedMemory32(Core::System& system, Handle shared_memory_handle, u32 addr,
@@ -1533,8 +1532,9 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1533 std::shared_ptr<KThread> thread; 1532 std::shared_ptr<KThread> thread;
1534 { 1533 {
1535 KScopedLightLock lk{process.GetStateLock()}; 1534 KScopedLightLock lk{process.GetStateLock()};
1536 CASCADE_RESULT(thread, KThread::Create(system, ThreadType::User, "", entry_point, priority, 1535 CASCADE_RESULT(thread,
1537 arg, core_id, stack_bottom, &process)); 1536 KThread::CreateUserThread(system, ThreadType::User, "", entry_point,
1537 priority, arg, core_id, stack_bottom, &process));
1538 } 1538 }
1539 1539
1540 const auto new_thread_handle = process.GetHandleTable().Create(thread); 1540 const auto new_thread_handle = process.GetHandleTable().Create(thread);
@@ -1638,7 +1638,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address,
1638 cv_key, tag, timeout_ns); 1638 cv_key, tag, timeout_ns);
1639 1639
1640 // Validate input. 1640 // Validate input.
1641 if (Memory::IsKernelAddress(address)) { 1641 if (IsKernelAddress(address)) {
1642 LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address); 1642 LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address);
1643 return ResultInvalidCurrentMemory; 1643 return ResultInvalidCurrentMemory;
1644 } 1644 }
@@ -1720,7 +1720,7 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::Arbit
1720 address, arb_type, value, timeout_ns); 1720 address, arb_type, value, timeout_ns);
1721 1721
1722 // Validate input. 1722 // Validate input.
1723 if (Memory::IsKernelAddress(address)) { 1723 if (IsKernelAddress(address)) {
1724 LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address); 1724 LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address);
1725 return ResultInvalidCurrentMemory; 1725 return ResultInvalidCurrentMemory;
1726 } 1726 }
@@ -1765,7 +1765,7 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign
1765 address, signal_type, value, count); 1765 address, signal_type, value, count);
1766 1766
1767 // Validate input. 1767 // Validate input.
1768 if (Memory::IsKernelAddress(address)) { 1768 if (IsKernelAddress(address)) {
1769 LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address); 1769 LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address);
1770 return ResultInvalidCurrentMemory; 1770 return ResultInvalidCurrentMemory;
1771 } 1771 }
@@ -1887,9 +1887,8 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
1887 return ResultInvalidCurrentMemory; 1887 return ResultInvalidCurrentMemory;
1888 } 1888 }
1889 1889
1890 const auto perms{static_cast<Memory::MemoryPermission>(permissions)}; 1890 const auto perms{static_cast<MemoryPermission>(permissions)};
1891 if (perms > Memory::MemoryPermission::ReadAndWrite || 1891 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})", 1892 LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
1894 permissions); 1893 permissions);
1895 return ResultInvalidMemoryPermissions; 1894 return ResultInvalidMemoryPermissions;
@@ -1903,7 +1902,8 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
1903 LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); 1902 LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory");
1904 return ResultResourceLimitedExceeded; 1903 return ResultResourceLimitedExceeded;
1905 } 1904 }
1906 auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms); 1905 auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size,
1906 static_cast<KMemoryPermission>(perms));
1907 1907
1908 if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { 1908 if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) {
1909 return reserve_result; 1909 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() {
24std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, 24std::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/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index b7b7bfeae..e7063f8ef 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -5,15 +5,25 @@
5#include <cstring> 5#include <cstring>
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "core/core_timing.h" 7#include "core/core_timing.h"
8#include "core/frontend/emu_window.h"
8#include "core/hle/service/hid/controllers/gesture.h" 9#include "core/hle/service/hid/controllers/gesture.h"
10#include "core/settings.h"
9 11
10namespace Service::HID { 12namespace Service::HID {
11constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; 13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00;
14constexpr f32 angle_threshold = 0.08f;
15constexpr f32 pinch_threshold = 100.0f;
12 16
13Controller_Gesture::Controller_Gesture(Core::System& system) : ControllerBase(system) {} 17Controller_Gesture::Controller_Gesture(Core::System& system) : ControllerBase(system) {}
14Controller_Gesture::~Controller_Gesture() = default; 18Controller_Gesture::~Controller_Gesture() = default;
15 19
16void Controller_Gesture::OnInit() {} 20void Controller_Gesture::OnInit() {
21 for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
22 mouse_finger_id[id] = MAX_FINGERS;
23 keyboard_finger_id[id] = MAX_FINGERS;
24 udp_finger_id[id] = MAX_FINGERS;
25 }
26}
17 27
18void Controller_Gesture::OnRelease() {} 28void Controller_Gesture::OnRelease() {}
19 29
@@ -35,10 +45,153 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
35 45
36 cur_entry.sampling_number = last_entry.sampling_number + 1; 46 cur_entry.sampling_number = last_entry.sampling_number + 1;
37 cur_entry.sampling_number2 = cur_entry.sampling_number; 47 cur_entry.sampling_number2 = cur_entry.sampling_number;
38 // TODO(ogniK): Update gesture states 48
49 // TODO(german77): Implement all gesture types
50
51 const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus();
52 const Input::TouchStatus& udp_status = touch_udp_device->GetStatus();
53 for (std::size_t id = 0; id < mouse_status.size(); ++id) {
54 mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]);
55 udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]);
56 }
57
58 if (Settings::values.use_touch_from_button) {
59 const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus();
60 for (std::size_t id = 0; id < mouse_status.size(); ++id) {
61 keyboard_finger_id[id] =
62 UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]);
63 }
64 }
65
66 TouchType type = TouchType::Idle;
67 Attribute attributes{};
68 GestureProperties gesture = GetGestureProperties();
69 if (last_gesture.active_points != gesture.active_points) {
70 ++last_gesture.detection_count;
71 }
72 if (gesture.active_points > 0) {
73 if (last_gesture.active_points == 0) {
74 attributes.is_new_touch.Assign(true);
75 last_gesture.average_distance = gesture.average_distance;
76 last_gesture.angle = gesture.angle;
77 }
78
79 type = TouchType::Touch;
80 if (gesture.mid_point.x != last_entry.x || gesture.mid_point.y != last_entry.y) {
81 type = TouchType::Pan;
82 }
83 if (std::abs(gesture.average_distance - last_gesture.average_distance) > pinch_threshold) {
84 type = TouchType::Pinch;
85 }
86 if (std::abs(gesture.angle - last_gesture.angle) > angle_threshold) {
87 type = TouchType::Rotate;
88 }
89
90 cur_entry.delta_x = gesture.mid_point.x - last_entry.x;
91 cur_entry.delta_y = gesture.mid_point.y - last_entry.y;
92 // TODO: Find how velocities are calculated
93 cur_entry.vel_x = static_cast<float>(cur_entry.delta_x) * 150.1f;
94 cur_entry.vel_y = static_cast<float>(cur_entry.delta_y) * 150.1f;
95
96 // Slowdown the rate of change for less flapping
97 last_gesture.average_distance =
98 (last_gesture.average_distance * 0.9f) + (gesture.average_distance * 0.1f);
99 last_gesture.angle = (last_gesture.angle * 0.9f) + (gesture.angle * 0.1f);
100
101 } else {
102 cur_entry.delta_x = 0;
103 cur_entry.delta_y = 0;
104 cur_entry.vel_x = 0;
105 cur_entry.vel_y = 0;
106 }
107 last_gesture.active_points = gesture.active_points;
108 cur_entry.detection_count = last_gesture.detection_count;
109 cur_entry.type = type;
110 cur_entry.attributes = attributes;
111 cur_entry.x = gesture.mid_point.x;
112 cur_entry.y = gesture.mid_point.y;
113 cur_entry.point_count = static_cast<s32>(gesture.active_points);
114 for (size_t id = 0; id < MAX_POINTS; id++) {
115 cur_entry.points[id].x = gesture.points[id].x;
116 cur_entry.points[id].y = gesture.points[id].y;
117 }
118 cur_entry.rotation_angle = 0;
119 cur_entry.scale = 0;
39 120
40 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); 121 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
41} 122}
42 123
43void Controller_Gesture::OnLoadInputDevices() {} 124void Controller_Gesture::OnLoadInputDevices() {
125 touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window");
126 touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp");
127 touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button");
128}
129
130std::optional<std::size_t> Controller_Gesture::GetUnusedFingerID() const {
131 std::size_t first_free_id = 0;
132 while (first_free_id < MAX_POINTS) {
133 if (!fingers[first_free_id].pressed) {
134 return first_free_id;
135 } else {
136 first_free_id++;
137 }
138 }
139 return std::nullopt;
140}
141
142std::size_t Controller_Gesture::UpdateTouchInputEvent(
143 const std::tuple<float, float, bool>& touch_input, std::size_t finger_id) {
144 const auto& [x, y, pressed] = touch_input;
145 if (pressed) {
146 if (finger_id == MAX_POINTS) {
147 const auto first_free_id = GetUnusedFingerID();
148 if (!first_free_id) {
149 // Invalid finger id do nothing
150 return MAX_POINTS;
151 }
152 finger_id = first_free_id.value();
153 fingers[finger_id].pressed = true;
154 }
155 fingers[finger_id].x = x;
156 fingers[finger_id].y = y;
157 return finger_id;
158 }
159
160 if (finger_id != MAX_POINTS) {
161 fingers[finger_id].pressed = false;
162 }
163
164 return MAX_POINTS;
165}
166
167Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() {
168 GestureProperties gesture;
169 std::array<Finger, MAX_POINTS> active_fingers;
170 const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(),
171 [](const auto& finger) { return finger.pressed; });
172 gesture.active_points =
173 static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));
174
175 for (size_t id = 0; id < gesture.active_points; ++id) {
176 gesture.points[id].x =
177 static_cast<int>(active_fingers[id].x * Layout::ScreenUndocked::Width);
178 gesture.points[id].y =
179 static_cast<int>(active_fingers[id].y * Layout::ScreenUndocked::Height);
180 gesture.mid_point.x += static_cast<int>(gesture.points[id].x / gesture.active_points);
181 gesture.mid_point.y += static_cast<int>(gesture.points[id].y / gesture.active_points);
182 }
183
184 for (size_t id = 0; id < gesture.active_points; ++id) {
185 const double distance =
186 std::pow(static_cast<float>(gesture.mid_point.x - gesture.points[id].x), 2) +
187 std::pow(static_cast<float>(gesture.mid_point.y - gesture.points[id].y), 2);
188 gesture.average_distance +=
189 static_cast<float>(distance) / static_cast<float>(gesture.active_points);
190 }
191
192 gesture.angle = std::atan2(static_cast<float>(gesture.mid_point.y - gesture.points[0].y),
193 static_cast<float>(gesture.mid_point.x - gesture.points[0].x));
194 return gesture;
195}
196
44} // namespace Service::HID 197} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index f650b8338..60ecc7822 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -5,8 +5,10 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include "common/bit_field.h"
8#include "common/common_types.h" 9#include "common/common_types.h"
9#include "common/swap.h" 10#include "common/swap.h"
11#include "core/frontend/input.h"
10#include "core/hle/service/hid/controllers/controller_base.h" 12#include "core/hle/service/hid/controllers/controller_base.h"
11 13
12namespace Service::HID { 14namespace Service::HID {
@@ -28,29 +30,64 @@ public:
28 void OnLoadInputDevices() override; 30 void OnLoadInputDevices() override;
29 31
30private: 32private:
31 struct Locations { 33 static constexpr size_t MAX_FINGERS = 16;
34 static constexpr size_t MAX_POINTS = 4;
35
36 enum class TouchType : u32 {
37 Idle, // Nothing touching the screen
38 Complete, // Unknown. End of touch?
39 Cancel, // Never triggered
40 Touch, // Pressing without movement
41 Press, // Never triggered
42 Tap, // Fast press then release
43 Pan, // All points moving together across the screen
44 Swipe, // Fast press movement and release of a single point
45 Pinch, // All points moving away/closer to the midpoint
46 Rotate, // All points rotating from the midpoint
47 };
48
49 enum class Direction : u32 {
50 None,
51 Left,
52 Up,
53 Right,
54 Down,
55 };
56
57 struct Attribute {
58 union {
59 u32_le raw{};
60
61 BitField<0, 1, u32> is_new_touch;
62 BitField<1, 1, u32> is_double_tap;
63 };
64 };
65 static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size");
66
67 struct Points {
32 s32_le x; 68 s32_le x;
33 s32_le y; 69 s32_le y;
34 }; 70 };
71 static_assert(sizeof(Points) == 8, "Points is an invalid size");
35 72
36 struct GestureState { 73 struct GestureState {
37 s64_le sampling_number; 74 s64_le sampling_number;
38 s64_le sampling_number2; 75 s64_le sampling_number2;
39 76
40 s64_le detection_count; 77 s64_le detection_count;
41 s32_le type; 78 TouchType type;
42 s32_le dir; 79 Direction dir;
43 s32_le x; 80 s32_le x;
44 s32_le y; 81 s32_le y;
45 s32_le delta_x; 82 s32_le delta_x;
46 s32_le delta_y; 83 s32_le delta_y;
47 f32 vel_x; 84 f32 vel_x;
48 f32 vel_y; 85 f32 vel_y;
49 s32_le attributes; 86 Attribute attributes;
50 f32 scale; 87 u32 scale;
51 f32 rotation; 88 u32 rotation_angle;
52 s32_le location_count; 89 s32_le point_count;
53 std::array<Locations, 4> locations; 90 std::array<Points, 4> points;
54 }; 91 };
55 static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size"); 92 static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size");
56 93
@@ -58,6 +95,45 @@ private:
58 CommonHeader header; 95 CommonHeader header;
59 std::array<GestureState, 17> gesture_states; 96 std::array<GestureState, 17> gesture_states;
60 }; 97 };
98 static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size");
99
100 struct Finger {
101 f32 x{};
102 f32 y{};
103 bool pressed{};
104 };
105
106 struct GestureProperties {
107 std::array<Points, MAX_POINTS> points{};
108 std::size_t active_points{};
109 Points mid_point{};
110 s64_le detection_count{};
111 u64_le delta_time{};
112 float average_distance{};
113 float angle{};
114 };
115
116 // Returns an unused finger id, if there is no fingers avaliable MAX_FINGERS will be returned
117 std::optional<size_t> GetUnusedFingerID() const;
118
119 /** If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no
120 * changes will be made. Updates the coordinates if the finger id it's already set. If the touch
121 * ends delays the output by one frame to set the end_touch flag before finally freeing the
122 * finger id */
123 size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input,
124 size_t finger_id);
125
126 // Returns the average distance, angle and middle point of the active fingers
127 GestureProperties GetGestureProperties();
128
61 SharedMemory shared_memory{}; 129 SharedMemory shared_memory{};
130 std::unique_ptr<Input::TouchDevice> touch_mouse_device;
131 std::unique_ptr<Input::TouchDevice> touch_udp_device;
132 std::unique_ptr<Input::TouchDevice> touch_btn_device;
133 std::array<size_t, MAX_FINGERS> mouse_finger_id;
134 std::array<size_t, MAX_FINGERS> keyboard_finger_id;
135 std::array<size_t, MAX_FINGERS> udp_finger_id;
136 std::array<Finger, MAX_POINTS> fingers;
137 GestureProperties last_gesture;
62}; 138};
63} // namespace Service::HID 139} // namespace Service::HID
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
16namespace Kernel { 16namespace Kernel {
17class SharedMemory; 17class KSharedMemory;
18} 18}
19 19
20namespace Service::SM { 20namespace 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
13namespace Service::HID { 13namespace 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
14namespace Kernel { 14namespace Kernel {
15class SharedMemory; 15class KSharedMemory;
16} 16}
17 17
18namespace Service::HID { 18namespace 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/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index c630d93cd..d160ffe87 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -156,7 +156,7 @@ public:
156 is_initialized = true; 156 is_initialized = true;
157 157
158 IPC::ResponseBuilder rb{ctx, 2}; 158 IPC::ResponseBuilder rb{ctx, 2};
159 rb.Push(RESULT_SUCCESS); 159 rb.Push(ERROR_DISABLED);
160 } 160 }
161 161
162private: 162private:
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
23SharedMemory::~SharedMemory() = default; 23SharedMemory::~SharedMemory() = default;
24 24
25std::shared_ptr<Kernel::SharedMemory> SharedMemory::GetSharedMemoryHolder() const { 25std::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
13namespace Service::Time { 13namespace 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
65private: 65private:
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/network/network.cpp b/src/core/network/network.cpp
index 681e93468..526bfa110 100644
--- a/src/core/network/network.cpp
+++ b/src/core/network/network.cpp
@@ -7,6 +7,7 @@
7#include <limits> 7#include <limits>
8#include <utility> 8#include <utility>
9#include <vector> 9#include <vector>
10#include "common/common_funcs.h"
10 11
11#ifdef _WIN32 12#ifdef _WIN32
12#define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname 13#define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname
@@ -90,15 +91,36 @@ LINGER MakeLinger(bool enable, u32 linger_value) {
90 return value; 91 return value;
91} 92}
92 93
93int LastError() {
94 return WSAGetLastError();
95}
96
97bool EnableNonBlock(SOCKET fd, bool enable) { 94bool EnableNonBlock(SOCKET fd, bool enable) {
98 u_long value = enable ? 1 : 0; 95 u_long value = enable ? 1 : 0;
99 return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR; 96 return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR;
100} 97}
101 98
99Errno TranslateNativeError(int e) {
100 switch (e) {
101 case WSAEBADF:
102 return Errno::BADF;
103 case WSAEINVAL:
104 return Errno::INVAL;
105 case WSAEMFILE:
106 return Errno::MFILE;
107 case WSAENOTCONN:
108 return Errno::NOTCONN;
109 case WSAEWOULDBLOCK:
110 return Errno::AGAIN;
111 case WSAECONNREFUSED:
112 return Errno::CONNREFUSED;
113 case WSAEHOSTUNREACH:
114 return Errno::HOSTUNREACH;
115 case WSAENETDOWN:
116 return Errno::NETDOWN;
117 case WSAENETUNREACH:
118 return Errno::NETUNREACH;
119 default:
120 return Errno::OTHER;
121 }
122}
123
102#elif YUZU_UNIX // ^ _WIN32 v YUZU_UNIX 124#elif YUZU_UNIX // ^ _WIN32 v YUZU_UNIX
103 125
104using SOCKET = int; 126using SOCKET = int;
@@ -108,9 +130,6 @@ using ULONG = u64;
108constexpr SOCKET INVALID_SOCKET = -1; 130constexpr SOCKET INVALID_SOCKET = -1;
109constexpr SOCKET SOCKET_ERROR = -1; 131constexpr SOCKET SOCKET_ERROR = -1;
110 132
111constexpr int WSAEWOULDBLOCK = EAGAIN;
112constexpr int WSAENOTCONN = ENOTCONN;
113
114constexpr int SD_RECEIVE = SHUT_RD; 133constexpr int SD_RECEIVE = SHUT_RD;
115constexpr int SD_SEND = SHUT_WR; 134constexpr int SD_SEND = SHUT_WR;
116constexpr int SD_BOTH = SHUT_RDWR; 135constexpr int SD_BOTH = SHUT_RDWR;
@@ -162,10 +181,6 @@ linger MakeLinger(bool enable, u32 linger_value) {
162 return value; 181 return value;
163} 182}
164 183
165int LastError() {
166 return errno;
167}
168
169bool EnableNonBlock(int fd, bool enable) { 184bool EnableNonBlock(int fd, bool enable) {
170 int flags = fcntl(fd, F_GETFD); 185 int flags = fcntl(fd, F_GETFD);
171 if (flags == -1) { 186 if (flags == -1) {
@@ -179,8 +194,43 @@ bool EnableNonBlock(int fd, bool enable) {
179 return fcntl(fd, F_SETFD, flags) == 0; 194 return fcntl(fd, F_SETFD, flags) == 0;
180} 195}
181 196
197Errno TranslateNativeError(int e) {
198 switch (e) {
199 case EBADF:
200 return Errno::BADF;
201 case EINVAL:
202 return Errno::INVAL;
203 case EMFILE:
204 return Errno::MFILE;
205 case ENOTCONN:
206 return Errno::NOTCONN;
207 case EAGAIN:
208 return Errno::AGAIN;
209 case ECONNREFUSED:
210 return Errno::CONNREFUSED;
211 case EHOSTUNREACH:
212 return Errno::HOSTUNREACH;
213 case ENETDOWN:
214 return Errno::NETDOWN;
215 case ENETUNREACH:
216 return Errno::NETUNREACH;
217 default:
218 return Errno::OTHER;
219 }
220}
221
182#endif 222#endif
183 223
224Errno GetAndLogLastError() {
225#ifdef _WIN32
226 int e = WSAGetLastError();
227#else
228 int e = errno;
229#endif
230 LOG_ERROR(Network, "Socket operation error: {}", NativeErrorToString(e));
231 return TranslateNativeError(e);
232}
233
184int TranslateDomain(Domain domain) { 234int TranslateDomain(Domain domain) {
185 switch (domain) { 235 switch (domain) {
186 case Domain::INET: 236 case Domain::INET:
@@ -290,9 +340,7 @@ Errno SetSockOpt(SOCKET fd, int option, T value) {
290 if (result != SOCKET_ERROR) { 340 if (result != SOCKET_ERROR) {
291 return Errno::SUCCESS; 341 return Errno::SUCCESS;
292 } 342 }
293 const int ec = LastError(); 343 return GetAndLogLastError();
294 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
295 return Errno::SUCCESS;
296} 344}
297 345
298} // Anonymous namespace 346} // Anonymous namespace
@@ -308,14 +356,12 @@ NetworkInstance::~NetworkInstance() {
308std::pair<IPv4Address, Errno> GetHostIPv4Address() { 356std::pair<IPv4Address, Errno> GetHostIPv4Address() {
309 std::array<char, 256> name{}; 357 std::array<char, 256> name{};
310 if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) { 358 if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) {
311 UNIMPLEMENTED_MSG("Unhandled gethostname error"); 359 return {IPv4Address{}, GetAndLogLastError()};
312 return {IPv4Address{}, Errno::SUCCESS};
313 } 360 }
314 361
315 hostent* const ent = gethostbyname(name.data()); 362 hostent* const ent = gethostbyname(name.data());
316 if (!ent) { 363 if (!ent) {
317 UNIMPLEMENTED_MSG("Unhandled gethostbyname error"); 364 return {IPv4Address{}, GetAndLogLastError()};
318 return {IPv4Address{}, Errno::SUCCESS};
319 } 365 }
320 if (ent->h_addr_list == nullptr) { 366 if (ent->h_addr_list == nullptr) {
321 UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list"); 367 UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list");
@@ -359,9 +405,7 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
359 405
360 ASSERT(result == SOCKET_ERROR); 406 ASSERT(result == SOCKET_ERROR);
361 407
362 const int ec = LastError(); 408 return {-1, GetAndLogLastError()};
363 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
364 return {-1, Errno::SUCCESS};
365} 409}
366 410
367Socket::~Socket() { 411Socket::~Socket() {
@@ -380,9 +424,7 @@ Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) {
380 return Errno::SUCCESS; 424 return Errno::SUCCESS;
381 } 425 }
382 426
383 const int ec = LastError(); 427 return GetAndLogLastError();
384 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
385 return Errno::SUCCESS;
386} 428}
387 429
388std::pair<Socket::AcceptResult, Errno> Socket::Accept() { 430std::pair<Socket::AcceptResult, Errno> Socket::Accept() {
@@ -391,9 +433,7 @@ std::pair<Socket::AcceptResult, Errno> Socket::Accept() {
391 const SOCKET new_socket = accept(fd, &addr, &addrlen); 433 const SOCKET new_socket = accept(fd, &addr, &addrlen);
392 434
393 if (new_socket == INVALID_SOCKET) { 435 if (new_socket == INVALID_SOCKET) {
394 const int ec = LastError(); 436 return {AcceptResult{}, GetAndLogLastError()};
395 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
396 return {AcceptResult{}, Errno::SUCCESS};
397 } 437 }
398 438
399 AcceptResult result; 439 AcceptResult result;
@@ -412,23 +452,14 @@ Errno Socket::Connect(SockAddrIn addr_in) {
412 return Errno::SUCCESS; 452 return Errno::SUCCESS;
413 } 453 }
414 454
415 switch (const int ec = LastError()) { 455 return GetAndLogLastError();
416 case WSAEWOULDBLOCK:
417 LOG_DEBUG(Service, "EAGAIN generated");
418 return Errno::AGAIN;
419 default:
420 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
421 return Errno::SUCCESS;
422 }
423} 456}
424 457
425std::pair<SockAddrIn, Errno> Socket::GetPeerName() { 458std::pair<SockAddrIn, Errno> Socket::GetPeerName() {
426 sockaddr addr; 459 sockaddr addr;
427 socklen_t addrlen = sizeof(addr); 460 socklen_t addrlen = sizeof(addr);
428 if (getpeername(fd, &addr, &addrlen) == SOCKET_ERROR) { 461 if (getpeername(fd, &addr, &addrlen) == SOCKET_ERROR) {
429 const int ec = LastError(); 462 return {SockAddrIn{}, GetAndLogLastError()};
430 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
431 return {SockAddrIn{}, Errno::SUCCESS};
432 } 463 }
433 464
434 ASSERT(addrlen == sizeof(sockaddr_in)); 465 ASSERT(addrlen == sizeof(sockaddr_in));
@@ -439,9 +470,7 @@ std::pair<SockAddrIn, Errno> Socket::GetSockName() {
439 sockaddr addr; 470 sockaddr addr;
440 socklen_t addrlen = sizeof(addr); 471 socklen_t addrlen = sizeof(addr);
441 if (getsockname(fd, &addr, &addrlen) == SOCKET_ERROR) { 472 if (getsockname(fd, &addr, &addrlen) == SOCKET_ERROR) {
442 const int ec = LastError(); 473 return {SockAddrIn{}, GetAndLogLastError()};
443 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
444 return {SockAddrIn{}, Errno::SUCCESS};
445 } 474 }
446 475
447 ASSERT(addrlen == sizeof(sockaddr_in)); 476 ASSERT(addrlen == sizeof(sockaddr_in));
@@ -454,9 +483,7 @@ Errno Socket::Bind(SockAddrIn addr) {
454 return Errno::SUCCESS; 483 return Errno::SUCCESS;
455 } 484 }
456 485
457 const int ec = LastError(); 486 return GetAndLogLastError();
458 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
459 return Errno::SUCCESS;
460} 487}
461 488
462Errno Socket::Listen(s32 backlog) { 489Errno Socket::Listen(s32 backlog) {
@@ -464,9 +491,7 @@ Errno Socket::Listen(s32 backlog) {
464 return Errno::SUCCESS; 491 return Errno::SUCCESS;
465 } 492 }
466 493
467 const int ec = LastError(); 494 return GetAndLogLastError();
468 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
469 return Errno::SUCCESS;
470} 495}
471 496
472Errno Socket::Shutdown(ShutdownHow how) { 497Errno Socket::Shutdown(ShutdownHow how) {
@@ -489,14 +514,7 @@ Errno Socket::Shutdown(ShutdownHow how) {
489 return Errno::SUCCESS; 514 return Errno::SUCCESS;
490 } 515 }
491 516
492 switch (const int ec = LastError()) { 517 return GetAndLogLastError();
493 case WSAENOTCONN:
494 LOG_ERROR(Service, "ENOTCONN generated");
495 return Errno::NOTCONN;
496 default:
497 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
498 return Errno::SUCCESS;
499 }
500} 518}
501 519
502std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) { 520std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) {
@@ -509,17 +527,7 @@ std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) {
509 return {static_cast<s32>(result), Errno::SUCCESS}; 527 return {static_cast<s32>(result), Errno::SUCCESS};
510 } 528 }
511 529
512 switch (const int ec = LastError()) { 530 return {-1, GetAndLogLastError()};
513 case WSAEWOULDBLOCK:
514 LOG_DEBUG(Service, "EAGAIN generated");
515 return {-1, Errno::AGAIN};
516 case WSAENOTCONN:
517 LOG_ERROR(Service, "ENOTCONN generated");
518 return {-1, Errno::NOTCONN};
519 default:
520 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
521 return {0, Errno::SUCCESS};
522 }
523} 531}
524 532
525std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) { 533std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) {
@@ -541,17 +549,7 @@ std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, Sock
541 return {static_cast<s32>(result), Errno::SUCCESS}; 549 return {static_cast<s32>(result), Errno::SUCCESS};
542 } 550 }
543 551
544 switch (const int ec = LastError()) { 552 return {-1, GetAndLogLastError()};
545 case WSAEWOULDBLOCK:
546 LOG_DEBUG(Service, "EAGAIN generated");
547 return {-1, Errno::AGAIN};
548 case WSAENOTCONN:
549 LOG_ERROR(Service, "ENOTCONN generated");
550 return {-1, Errno::NOTCONN};
551 default:
552 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
553 return {-1, Errno::SUCCESS};
554 }
555} 553}
556 554
557std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) { 555std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
@@ -564,18 +562,7 @@ std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
564 return {static_cast<s32>(result), Errno::SUCCESS}; 562 return {static_cast<s32>(result), Errno::SUCCESS};
565 } 563 }
566 564
567 const int ec = LastError(); 565 return {-1, GetAndLogLastError()};
568 switch (ec) {
569 case WSAEWOULDBLOCK:
570 LOG_DEBUG(Service, "EAGAIN generated");
571 return {-1, Errno::AGAIN};
572 case WSAENOTCONN:
573 LOG_ERROR(Service, "ENOTCONN generated");
574 return {-1, Errno::NOTCONN};
575 default:
576 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
577 return {-1, Errno::SUCCESS};
578 }
579} 566}
580 567
581std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message, 568std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
@@ -597,9 +584,7 @@ std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
597 return {static_cast<s32>(result), Errno::SUCCESS}; 584 return {static_cast<s32>(result), Errno::SUCCESS};
598 } 585 }
599 586
600 const int ec = LastError(); 587 return {-1, GetAndLogLastError()};
601 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
602 return {-1, Errno::SUCCESS};
603} 588}
604 589
605Errno Socket::Close() { 590Errno Socket::Close() {
@@ -642,9 +627,7 @@ Errno Socket::SetNonBlock(bool enable) {
642 if (EnableNonBlock(fd, enable)) { 627 if (EnableNonBlock(fd, enable)) {
643 return Errno::SUCCESS; 628 return Errno::SUCCESS;
644 } 629 }
645 const int ec = LastError(); 630 return GetAndLogLastError();
646 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
647 return Errno::SUCCESS;
648} 631}
649 632
650bool Socket::IsOpened() const { 633bool Socket::IsOpened() const {
diff --git a/src/core/network/network.h b/src/core/network/network.h
index 76b2821f2..bd30f1899 100644
--- a/src/core/network/network.h
+++ b/src/core/network/network.h
@@ -7,6 +7,7 @@
7#include <array> 7#include <array>
8#include <utility> 8#include <utility>
9 9
10#include "common/common_funcs.h"
10#include "common/common_types.h" 11#include "common/common_types.h"
11 12
12namespace Network { 13namespace Network {
@@ -21,6 +22,11 @@ enum class Errno {
21 MFILE, 22 MFILE,
22 NOTCONN, 23 NOTCONN,
23 AGAIN, 24 AGAIN,
25 CONNREFUSED,
26 HOSTUNREACH,
27 NETDOWN,
28 NETUNREACH,
29 OTHER,
24}; 30};
25 31
26/// Address families 32/// Address families
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/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index c4afa4174..df73f9ff7 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -5,6 +5,7 @@
5#include <chrono> 5#include <chrono>
6#include <cstring> 6#include <cstring>
7#include <functional> 7#include <functional>
8#include <random>
8#include <thread> 9#include <thread>
9#include <boost/asio.hpp> 10#include <boost/asio.hpp>
10#include "common/logging/log.h" 11#include "common/logging/log.h"
@@ -26,10 +27,10 @@ class Socket {
26public: 27public:
27 using clock = std::chrono::system_clock; 28 using clock = std::chrono::system_clock;
28 29
29 explicit Socket(const std::string& host, u16 port, std::size_t pad_index_, u32 client_id_, 30 explicit Socket(const std::string& host, u16 port, std::size_t pad_index_,
30 SocketCallback callback_) 31 SocketCallback callback_)
31 : callback(std::move(callback_)), timer(io_service), 32 : callback(std::move(callback_)), timer(io_service),
32 socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(client_id_), 33 socket(io_service, udp::endpoint(udp::v4(), 0)), client_id(GenerateRandomClientId()),
33 pad_index(pad_index_) { 34 pad_index(pad_index_) {
34 boost::system::error_code ec{}; 35 boost::system::error_code ec{};
35 auto ipv4 = boost::asio::ip::make_address_v4(host, ec); 36 auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
@@ -63,6 +64,11 @@ public:
63 } 64 }
64 65
65private: 66private:
67 u32 GenerateRandomClientId() const {
68 std::random_device device;
69 return device();
70 }
71
66 void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) { 72 void HandleReceive(const boost::system::error_code&, std::size_t bytes_transferred) {
67 if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) { 73 if (auto type = Response::Validate(receive_buffer.data(), bytes_transferred)) {
68 switch (*type) { 74 switch (*type) {
@@ -115,7 +121,7 @@ private:
115 boost::asio::basic_waitable_timer<clock> timer; 121 boost::asio::basic_waitable_timer<clock> timer;
116 udp::socket socket; 122 udp::socket socket;
117 123
118 u32 client_id{}; 124 const u32 client_id;
119 std::size_t pad_index{}; 125 std::size_t pad_index{};
120 126
121 static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>); 127 static constexpr std::size_t PORT_INFO_SIZE = sizeof(Message<Request::PortInfo>);
@@ -203,7 +209,7 @@ void Client::ReloadSockets() {
203 LOG_ERROR(Input, "Duplicated UDP servers found"); 209 LOG_ERROR(Input, "Duplicated UDP servers found");
204 continue; 210 continue;
205 } 211 }
206 StartCommunication(client++, udp_input_address, udp_input_port, pad, 24872); 212 StartCommunication(client++, udp_input_address, udp_input_port, pad);
207 } 213 }
208 } 214 }
209} 215}
@@ -277,7 +283,7 @@ void Client::OnPadData(Response::PadData data, std::size_t client) {
277} 283}
278 284
279void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, 285void Client::StartCommunication(std::size_t client, const std::string& host, u16 port,
280 std::size_t pad_index, u32 client_id) { 286 std::size_t pad_index) {
281 SocketCallback callback{[this](Response::Version version) { OnVersion(version); }, 287 SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
282 [this](Response::PortInfo info) { OnPortInfo(info); }, 288 [this](Response::PortInfo info) { OnPortInfo(info); },
283 [this, client](Response::PadData data) { OnPadData(data, client); }}; 289 [this, client](Response::PadData data) { OnPadData(data, client); }};
@@ -287,7 +293,7 @@ void Client::StartCommunication(std::size_t client, const std::string& host, u16
287 clients[client].port = port; 293 clients[client].port = port;
288 clients[client].pad_index = pad_index; 294 clients[client].pad_index = pad_index;
289 clients[client].active = 0; 295 clients[client].active = 0;
290 clients[client].socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback); 296 clients[client].socket = std::make_unique<Socket>(host, port, pad_index, callback);
291 clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()}; 297 clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
292 // Set motion parameters 298 // Set motion parameters
293 // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode 299 // SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
@@ -416,7 +422,7 @@ const Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() const {
416 return pad_queue; 422 return pad_queue;
417} 423}
418 424
419void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, u32 client_id, 425void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
420 const std::function<void()>& success_callback, 426 const std::function<void()>& success_callback,
421 const std::function<void()>& failure_callback) { 427 const std::function<void()>& failure_callback) {
422 std::thread([=] { 428 std::thread([=] {
@@ -426,7 +432,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
426 .port_info = [](Response::PortInfo) {}, 432 .port_info = [](Response::PortInfo) {},
427 .pad_data = [&](Response::PadData) { success_event.Set(); }, 433 .pad_data = [&](Response::PadData) { success_event.Set(); },
428 }; 434 };
429 Socket socket{host, port, pad_index, client_id, std::move(callback)}; 435 Socket socket{host, port, pad_index, std::move(callback)};
430 std::thread worker_thread{SocketLoop, &socket}; 436 std::thread worker_thread{SocketLoop, &socket};
431 const bool result = success_event.WaitFor(std::chrono::seconds(5)); 437 const bool result = success_event.WaitFor(std::chrono::seconds(5));
432 socket.Stop(); 438 socket.Stop();
@@ -440,7 +446,7 @@ void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
440} 446}
441 447
442CalibrationConfigurationJob::CalibrationConfigurationJob( 448CalibrationConfigurationJob::CalibrationConfigurationJob(
443 const std::string& host, u16 port, std::size_t pad_index, u32 client_id, 449 const std::string& host, u16 port, std::size_t pad_index,
444 std::function<void(Status)> status_callback, 450 std::function<void(Status)> status_callback,
445 std::function<void(u16, u16, u16, u16)> data_callback) { 451 std::function<void(u16, u16, u16, u16)> data_callback) {
446 452
@@ -485,7 +491,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
485 complete_event.Set(); 491 complete_event.Set();
486 } 492 }
487 }}; 493 }};
488 Socket socket{host, port, pad_index, client_id, std::move(callback)}; 494 Socket socket{host, port, pad_index, std::move(callback)};
489 std::thread worker_thread{SocketLoop, &socket}; 495 std::thread worker_thread{SocketLoop, &socket};
490 complete_event.Wait(); 496 complete_event.Wait();
491 socket.Stop(); 497 socket.Stop();
diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h
index a523f6124..e9e438e88 100644
--- a/src/input_common/udp/client.h
+++ b/src/input_common/udp/client.h
@@ -126,7 +126,7 @@ private:
126 void OnPortInfo(Response::PortInfo); 126 void OnPortInfo(Response::PortInfo);
127 void OnPadData(Response::PadData, std::size_t client); 127 void OnPadData(Response::PadData, std::size_t client);
128 void StartCommunication(std::size_t client, const std::string& host, u16 port, 128 void StartCommunication(std::size_t client, const std::string& host, u16 port,
129 std::size_t pad_index, u32 client_id); 129 std::size_t pad_index);
130 void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, 130 void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
131 const Common::Vec3<float>& gyro); 131 const Common::Vec3<float>& gyro);
132 132
@@ -165,7 +165,7 @@ public:
165 * @param data_callback Called when calibration data is ready 165 * @param data_callback Called when calibration data is ready
166 */ 166 */
167 explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index, 167 explicit CalibrationConfigurationJob(const std::string& host, u16 port, std::size_t pad_index,
168 u32 client_id, std::function<void(Status)> status_callback, 168 std::function<void(Status)> status_callback,
169 std::function<void(u16, u16, u16, u16)> data_callback); 169 std::function<void(u16, u16, u16, u16)> data_callback);
170 ~CalibrationConfigurationJob(); 170 ~CalibrationConfigurationJob();
171 void Stop(); 171 void Stop();
@@ -174,7 +174,7 @@ private:
174 Common::Event complete_event; 174 Common::Event complete_event;
175}; 175};
176 176
177void TestCommunication(const std::string& host, u16 port, std::size_t pad_index, u32 client_id, 177void TestCommunication(const std::string& host, u16 port, std::size_t pad_index,
178 const std::function<void()>& success_callback, 178 const std::function<void()>& success_callback,
179 const std::function<void()>& failure_callback); 179 const std::function<void()>& failure_callback);
180 180
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 4ea0076e9..d875c4fee 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -5,6 +5,7 @@ add_executable(tests
5 common/param_package.cpp 5 common/param_package.cpp
6 common/ring_buffer.cpp 6 common/ring_buffer.cpp
7 core/core_timing.cpp 7 core/core_timing.cpp
8 core/network/network.cpp
8 tests.cpp 9 tests.cpp
9 video_core/buffer_base.cpp 10 video_core/buffer_base.cpp
10) 11)
diff --git a/src/tests/common/fibers.cpp b/src/tests/common/fibers.cpp
index d94492fc6..751cbe196 100644
--- a/src/tests/common/fibers.cpp
+++ b/src/tests/common/fibers.cpp
@@ -67,7 +67,7 @@ void TestControl1::DoWork() {
67 value++; 67 value++;
68 } 68 }
69 results[id] = value; 69 results[id] = value;
70 Fiber::YieldTo(work_fibers[id], thread_fibers[id]); 70 Fiber::YieldTo(work_fibers[id], *thread_fibers[id]);
71} 71}
72 72
73void TestControl1::ExecuteThread(u32 id) { 73void TestControl1::ExecuteThread(u32 id) {
@@ -76,7 +76,7 @@ void TestControl1::ExecuteThread(u32 id) {
76 thread_fibers[id] = thread_fiber; 76 thread_fibers[id] = thread_fiber;
77 work_fibers[id] = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl1}, this); 77 work_fibers[id] = std::make_shared<Fiber>(std::function<void(void*)>{WorkControl1}, this);
78 items[id] = rand() % 256; 78 items[id] = rand() % 256;
79 Fiber::YieldTo(thread_fibers[id], work_fibers[id]); 79 Fiber::YieldTo(thread_fibers[id], *work_fibers[id]);
80 thread_fibers[id]->Exit(); 80 thread_fibers[id]->Exit();
81} 81}
82 82
@@ -117,11 +117,11 @@ public:
117 for (u32 i = 0; i < 12000; i++) { 117 for (u32 i = 0; i < 12000; i++) {
118 value1 += i; 118 value1 += i;
119 } 119 }
120 Fiber::YieldTo(fiber1, fiber3); 120 Fiber::YieldTo(fiber1, *fiber3);
121 const u32 id = thread_ids.Get(); 121 const u32 id = thread_ids.Get();
122 assert1 = id == 1; 122 assert1 = id == 1;
123 value2 += 5000; 123 value2 += 5000;
124 Fiber::YieldTo(fiber1, thread_fibers[id]); 124 Fiber::YieldTo(fiber1, *thread_fibers[id]);
125 } 125 }
126 126
127 void DoWork2() { 127 void DoWork2() {
@@ -129,7 +129,7 @@ public:
129 ; 129 ;
130 value2 = 2000; 130 value2 = 2000;
131 trap = false; 131 trap = false;
132 Fiber::YieldTo(fiber2, fiber1); 132 Fiber::YieldTo(fiber2, *fiber1);
133 assert3 = false; 133 assert3 = false;
134 } 134 }
135 135
@@ -137,19 +137,19 @@ public:
137 const u32 id = thread_ids.Get(); 137 const u32 id = thread_ids.Get();
138 assert2 = id == 0; 138 assert2 = id == 0;
139 value1 += 1000; 139 value1 += 1000;
140 Fiber::YieldTo(fiber3, thread_fibers[id]); 140 Fiber::YieldTo(fiber3, *thread_fibers[id]);
141 } 141 }
142 142
143 void ExecuteThread(u32 id); 143 void ExecuteThread(u32 id);
144 144
145 void CallFiber1() { 145 void CallFiber1() {
146 const u32 id = thread_ids.Get(); 146 const u32 id = thread_ids.Get();
147 Fiber::YieldTo(thread_fibers[id], fiber1); 147 Fiber::YieldTo(thread_fibers[id], *fiber1);
148 } 148 }
149 149
150 void CallFiber2() { 150 void CallFiber2() {
151 const u32 id = thread_ids.Get(); 151 const u32 id = thread_ids.Get();
152 Fiber::YieldTo(thread_fibers[id], fiber2); 152 Fiber::YieldTo(thread_fibers[id], *fiber2);
153 } 153 }
154 154
155 void Exit(); 155 void Exit();
@@ -241,23 +241,23 @@ public:
241 241
242 void DoWork1() { 242 void DoWork1() {
243 value1 += 1; 243 value1 += 1;
244 Fiber::YieldTo(fiber1, fiber2); 244 Fiber::YieldTo(fiber1, *fiber2);
245 const u32 id = thread_ids.Get(); 245 const u32 id = thread_ids.Get();
246 value3 += 1; 246 value3 += 1;
247 Fiber::YieldTo(fiber1, thread_fibers[id]); 247 Fiber::YieldTo(fiber1, *thread_fibers[id]);
248 } 248 }
249 249
250 void DoWork2() { 250 void DoWork2() {
251 value2 += 1; 251 value2 += 1;
252 const u32 id = thread_ids.Get(); 252 const u32 id = thread_ids.Get();
253 Fiber::YieldTo(fiber2, thread_fibers[id]); 253 Fiber::YieldTo(fiber2, *thread_fibers[id]);
254 } 254 }
255 255
256 void ExecuteThread(u32 id); 256 void ExecuteThread(u32 id);
257 257
258 void CallFiber1() { 258 void CallFiber1() {
259 const u32 id = thread_ids.Get(); 259 const u32 id = thread_ids.Get();
260 Fiber::YieldTo(thread_fibers[id], fiber1); 260 Fiber::YieldTo(thread_fibers[id], *fiber1);
261 } 261 }
262 262
263 void Exit(); 263 void Exit();
@@ -332,7 +332,7 @@ public:
332 332
333 void Execute() { 333 void Execute() {
334 thread_fiber = Fiber::ThreadToFiber(); 334 thread_fiber = Fiber::ThreadToFiber();
335 Fiber::YieldTo(thread_fiber, fiber1); 335 Fiber::YieldTo(thread_fiber, *fiber1);
336 thread_fiber->Exit(); 336 thread_fiber->Exit();
337 } 337 }
338 338
@@ -340,7 +340,7 @@ public:
340 fiber1->SetRewindPoint(std::function<void(void*)>{WorkControl4}, this); 340 fiber1->SetRewindPoint(std::function<void(void*)>{WorkControl4}, this);
341 if (rewinded) { 341 if (rewinded) {
342 goal_reached = true; 342 goal_reached = true;
343 Fiber::YieldTo(fiber1, thread_fiber); 343 Fiber::YieldTo(fiber1, *thread_fiber);
344 } 344 }
345 rewinded = true; 345 rewinded = true;
346 fiber1->Rewind(); 346 fiber1->Rewind();
diff --git a/src/tests/core/network/network.cpp b/src/tests/core/network/network.cpp
new file mode 100644
index 000000000..b21ad8911
--- /dev/null
+++ b/src/tests/core/network/network.cpp
@@ -0,0 +1,28 @@
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 <catch2/catch.hpp>
6
7#include "core/network/network.h"
8#include "core/network/sockets.h"
9
10TEST_CASE("Network::Errors", "[core]") {
11 Network::NetworkInstance network_instance; // initialize network
12
13 Network::Socket socks[2];
14 for (Network::Socket& sock : socks) {
15 REQUIRE(sock.Initialize(Network::Domain::INET, Network::Type::STREAM,
16 Network::Protocol::TCP) == Network::Errno::SUCCESS);
17 }
18
19 Network::SockAddrIn addr{
20 Network::Domain::INET,
21 {127, 0, 0, 1},
22 1, // hopefully nobody running this test has something listening on port 1
23 };
24 REQUIRE(socks[0].Connect(addr) == Network::Errno::CONNREFUSED);
25
26 std::vector<u8> message{1, 2, 3, 4};
27 REQUIRE(socks[1].Recv(0, message).second == Network::Errno::NOTCONN);
28}
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 51c63af4a..c61f44619 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -459,7 +459,7 @@ void GPU::ProcessSemaphoreAcquire() {
459} 459}
460 460
461void GPU::Start() { 461void GPU::Start() {
462 gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher, *cdma_pusher); 462 gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher);
463 cpu_context = renderer->GetRenderWindow().CreateSharedContext(); 463 cpu_context = renderer->GetRenderWindow().CreateSharedContext();
464 cpu_context->MakeCurrent(); 464 cpu_context->MakeCurrent();
465} 465}
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index eb0e43c0c..99353f15f 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -19,7 +19,7 @@ namespace VideoCommon::GPUThread {
19/// Runs the GPU thread 19/// Runs the GPU thread
20static void RunThread(Core::System& system, VideoCore::RendererBase& renderer, 20static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
21 Core::Frontend::GraphicsContext& context, Tegra::DmaPusher& dma_pusher, 21 Core::Frontend::GraphicsContext& context, Tegra::DmaPusher& dma_pusher,
22 SynchState& state, Tegra::CDmaPusher& cdma_pusher) { 22 SynchState& state) {
23 std::string name = "yuzu:GPU"; 23 std::string name = "yuzu:GPU";
24 MicroProfileOnThreadCreate(name.c_str()); 24 MicroProfileOnThreadCreate(name.c_str());
25 SCOPE_EXIT({ MicroProfileOnThreadExit(); }); 25 SCOPE_EXIT({ MicroProfileOnThreadExit(); });
@@ -46,9 +46,6 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
46 if (auto* submit_list = std::get_if<SubmitListCommand>(&next.data)) { 46 if (auto* submit_list = std::get_if<SubmitListCommand>(&next.data)) {
47 dma_pusher.Push(std::move(submit_list->entries)); 47 dma_pusher.Push(std::move(submit_list->entries));
48 dma_pusher.DispatchCalls(); 48 dma_pusher.DispatchCalls();
49 } else if (auto* command_list = std::get_if<SubmitChCommandEntries>(&next.data)) {
50 // NVDEC
51 cdma_pusher.ProcessEntries(std::move(command_list->entries));
52 } else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) { 49 } else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) {
53 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr); 50 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
54 } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) { 51 } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) {
@@ -83,20 +80,16 @@ ThreadManager::~ThreadManager() {
83 80
84void ThreadManager::StartThread(VideoCore::RendererBase& renderer, 81void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
85 Core::Frontend::GraphicsContext& context, 82 Core::Frontend::GraphicsContext& context,
86 Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher) { 83 Tegra::DmaPusher& dma_pusher) {
87 rasterizer = renderer.ReadRasterizer(); 84 rasterizer = renderer.ReadRasterizer();
88 thread = std::thread(RunThread, std::ref(system), std::ref(renderer), std::ref(context), 85 thread = std::thread(RunThread, std::ref(system), std::ref(renderer), std::ref(context),
89 std::ref(dma_pusher), std::ref(state), std::ref(cdma_pusher)); 86 std::ref(dma_pusher), std::ref(state));
90} 87}
91 88
92void ThreadManager::SubmitList(Tegra::CommandList&& entries) { 89void ThreadManager::SubmitList(Tegra::CommandList&& entries) {
93 PushCommand(SubmitListCommand(std::move(entries))); 90 PushCommand(SubmitListCommand(std::move(entries)));
94} 91}
95 92
96void ThreadManager::SubmitCommandBuffer(Tegra::ChCommandHeaderList&& entries) {
97 PushCommand(SubmitChCommandEntries(std::move(entries)));
98}
99
100void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { 93void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
101 PushCommand(SwapBuffersCommand(framebuffer ? std::make_optional(*framebuffer) : std::nullopt)); 94 PushCommand(SwapBuffersCommand(framebuffer ? std::make_optional(*framebuffer) : std::nullopt));
102} 95}
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index 4cd951169..18269e51c 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -43,14 +43,6 @@ struct SubmitListCommand final {
43 Tegra::CommandList entries; 43 Tegra::CommandList entries;
44}; 44};
45 45
46/// Command to signal to the GPU thread that a cdma command list is ready for processing
47struct SubmitChCommandEntries final {
48 explicit SubmitChCommandEntries(Tegra::ChCommandHeaderList&& entries_)
49 : entries{std::move(entries_)} {}
50
51 Tegra::ChCommandHeaderList entries;
52};
53
54/// Command to signal to the GPU thread that a swap buffers is pending 46/// Command to signal to the GPU thread that a swap buffers is pending
55struct SwapBuffersCommand final { 47struct SwapBuffersCommand final {
56 explicit SwapBuffersCommand(std::optional<const Tegra::FramebufferConfig> framebuffer_) 48 explicit SwapBuffersCommand(std::optional<const Tegra::FramebufferConfig> framebuffer_)
@@ -91,9 +83,9 @@ struct OnCommandListEndCommand final {};
91struct GPUTickCommand final {}; 83struct GPUTickCommand final {};
92 84
93using CommandData = 85using CommandData =
94 std::variant<EndProcessingCommand, SubmitListCommand, SubmitChCommandEntries, 86 std::variant<EndProcessingCommand, SubmitListCommand, SwapBuffersCommand, FlushRegionCommand,
95 SwapBuffersCommand, FlushRegionCommand, InvalidateRegionCommand, 87 InvalidateRegionCommand, FlushAndInvalidateRegionCommand, OnCommandListEndCommand,
96 FlushAndInvalidateRegionCommand, OnCommandListEndCommand, GPUTickCommand>; 88 GPUTickCommand>;
97 89
98struct CommandDataContainer { 90struct CommandDataContainer {
99 CommandDataContainer() = default; 91 CommandDataContainer() = default;
@@ -123,14 +115,11 @@ public:
123 115
124 /// Creates and starts the GPU thread. 116 /// Creates and starts the GPU thread.
125 void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context, 117 void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
126 Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher); 118 Tegra::DmaPusher& dma_pusher);
127 119
128 /// Push GPU command entries to be processed 120 /// Push GPU command entries to be processed
129 void SubmitList(Tegra::CommandList&& entries); 121 void SubmitList(Tegra::CommandList&& entries);
130 122
131 /// Push GPU CDMA command buffer entries to be processed
132 void SubmitCommandBuffer(Tegra::ChCommandHeaderList&& entries);
133
134 /// Swap buffers (render frame) 123 /// Swap buffers (render frame)
135 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); 124 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
136 125
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"
diff --git a/src/video_core/renderer_vulkan/vk_command_pool.cpp b/src/video_core/renderer_vulkan/vk_command_pool.cpp
index a99df9323..d8e92ac0e 100644
--- a/src/video_core/renderer_vulkan/vk_command_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_command_pool.cpp
@@ -10,7 +10,7 @@
10 10
11namespace Vulkan { 11namespace Vulkan {
12 12
13constexpr size_t COMMAND_BUFFER_POOL_SIZE = 0x1000; 13constexpr size_t COMMAND_BUFFER_POOL_SIZE = 4;
14 14
15struct CommandPool::Pool { 15struct CommandPool::Pool {
16 vk::CommandPool handle; 16 vk::CommandPool handle;
diff --git a/src/video_core/shader_notify.cpp b/src/video_core/shader_notify.cpp
index c3c71657d..693e47158 100644
--- a/src/video_core/shader_notify.cpp
+++ b/src/video_core/shader_notify.cpp
@@ -2,6 +2,7 @@
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 <mutex>
5#include "video_core/shader_notify.h" 6#include "video_core/shader_notify.h"
6 7
7using namespace std::chrono_literals; 8using namespace std::chrono_literals;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index e6537d295..1bac57bb2 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -648,7 +648,7 @@ void Config::ReadDebuggingValues() {
648void Config::ReadServiceValues() { 648void Config::ReadServiceValues() {
649 qt_config->beginGroup(QStringLiteral("Services")); 649 qt_config->beginGroup(QStringLiteral("Services"));
650 Settings::values.bcat_backend = 650 Settings::values.bcat_backend =
651 ReadSetting(QStringLiteral("bcat_backend"), QStringLiteral("null")) 651 ReadSetting(QStringLiteral("bcat_backend"), QStringLiteral("none"))
652 .toString() 652 .toString()
653 .toStdString(); 653 .toStdString();
654 Settings::values.bcat_boxcat_local = 654 Settings::values.bcat_boxcat_local =
@@ -1238,7 +1238,7 @@ void Config::SaveDebuggingValues() {
1238void Config::SaveServiceValues() { 1238void Config::SaveServiceValues() {
1239 qt_config->beginGroup(QStringLiteral("Services")); 1239 qt_config->beginGroup(QStringLiteral("Services"));
1240 WriteSetting(QStringLiteral("bcat_backend"), 1240 WriteSetting(QStringLiteral("bcat_backend"),
1241 QString::fromStdString(Settings::values.bcat_backend), QStringLiteral("null")); 1241 QString::fromStdString(Settings::values.bcat_backend), QStringLiteral("none"));
1242 WriteSetting(QStringLiteral("bcat_boxcat_local"), Settings::values.bcat_boxcat_local, false); 1242 WriteSetting(QStringLiteral("bcat_boxcat_local"), Settings::values.bcat_boxcat_local, false);
1243 qt_config->endGroup(); 1243 qt_config->endGroup();
1244} 1244}
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index 1f2b792e4..52fdf7265 100644
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -24,7 +24,7 @@
24 24
25CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent, 25CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
26 const std::string& host, u16 port, 26 const std::string& host, u16 port,
27 u8 pad_index, u16 client_id) 27 u8 pad_index)
28 : QDialog(parent) { 28 : QDialog(parent) {
29 layout = new QVBoxLayout; 29 layout = new QVBoxLayout;
30 status_label = new QLabel(tr("Communicating with the server...")); 30 status_label = new QLabel(tr("Communicating with the server..."));
@@ -41,7 +41,7 @@ CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
41 41
42 using namespace InputCommon::CemuhookUDP; 42 using namespace InputCommon::CemuhookUDP;
43 job = std::make_unique<CalibrationConfigurationJob>( 43 job = std::make_unique<CalibrationConfigurationJob>(
44 host, port, pad_index, client_id, 44 host, port, pad_index,
45 [this](CalibrationConfigurationJob::Status status) { 45 [this](CalibrationConfigurationJob::Status status) {
46 QString text; 46 QString text;
47 switch (status) { 47 switch (status) {
@@ -218,7 +218,6 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() {
218 udp_test_in_progress = true; 218 udp_test_in_progress = true;
219 InputCommon::CemuhookUDP::TestCommunication( 219 InputCommon::CemuhookUDP::TestCommunication(
220 ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), 0, 220 ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()), 0,
221 24872,
222 [this] { 221 [this] {
223 LOG_INFO(Frontend, "UDP input test success"); 222 LOG_INFO(Frontend, "UDP input test success");
224 QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); 223 QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true));
@@ -233,8 +232,7 @@ void ConfigureMotionTouch::OnConfigureTouchCalibration() {
233 ui->touch_calibration_config->setEnabled(false); 232 ui->touch_calibration_config->setEnabled(false);
234 ui->touch_calibration_config->setText(tr("Configuring")); 233 ui->touch_calibration_config->setText(tr("Configuring"));
235 CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(), 234 CalibrationConfigurationDialog dialog(this, ui->udp_server->text().toStdString(),
236 static_cast<u16>(ui->udp_port->text().toUInt()), 0, 235 static_cast<u16>(ui->udp_port->text().toUInt()), 0);
237 24872);
238 dialog.exec(); 236 dialog.exec();
239 if (dialog.completed) { 237 if (dialog.completed) {
240 min_x = dialog.min_x; 238 min_x = dialog.min_x;
diff --git a/src/yuzu/configuration/configure_motion_touch.h b/src/yuzu/configuration/configure_motion_touch.h
index 15d61e8ba..d76bc8154 100644
--- a/src/yuzu/configuration/configure_motion_touch.h
+++ b/src/yuzu/configuration/configure_motion_touch.h
@@ -30,7 +30,7 @@ class CalibrationConfigurationDialog : public QDialog {
30 Q_OBJECT 30 Q_OBJECT
31public: 31public:
32 explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port, 32 explicit CalibrationConfigurationDialog(QWidget* parent, const std::string& host, u16 port,
33 u8 pad_index, u16 client_id); 33 u8 pad_index);
34 ~CalibrationConfigurationDialog() override; 34 ~CalibrationConfigurationDialog() override;
35 35
36private: 36private:
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 6d8bc5509..43877fc98 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -457,7 +457,7 @@ void Config::ReadValues() {
457 Settings::values.yuzu_token = sdl2_config->Get("WebService", "yuzu_token", ""); 457 Settings::values.yuzu_token = sdl2_config->Get("WebService", "yuzu_token", "");
458 458
459 // Services 459 // Services
460 Settings::values.bcat_backend = sdl2_config->Get("Services", "bcat_backend", "null"); 460 Settings::values.bcat_backend = sdl2_config->Get("Services", "bcat_backend", "none");
461 Settings::values.bcat_boxcat_local = 461 Settings::values.bcat_boxcat_local =
462 sdl2_config->GetBoolean("Services", "bcat_boxcat_local", false); 462 sdl2_config->GetBoolean("Services", "bcat_boxcat_local", false);
463} 463}