summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/common_sizes.h43
-rw-r--r--src/common/logging/backend.cpp1
-rw-r--r--src/common/logging/log.h1
-rw-r--r--src/common/threadsafe_queue.h10
-rw-r--r--src/core/CMakeLists.txt9
-rw-r--r--src/core/core.cpp2
-rw-r--r--src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc20
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc52
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp164
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/k_system_control.h28
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/secure_monitor.h26
-rw-r--r--src/core/hle/kernel/k_address_space_info.cpp43
-rw-r--r--src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp199
-rw-r--r--src/core/hle/kernel/k_memory_layout.cpp166
-rw-r--r--src/core/hle/kernel/k_memory_layout.h397
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp12
-rw-r--r--src/core/hle/kernel/k_memory_manager.h18
-rw-r--r--src/core/hle/kernel/k_memory_region.h350
-rw-r--r--src/core/hle/kernel/k_memory_region_type.h338
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp22
-rw-r--r--src/core/hle/kernel/k_scheduler.h11
-rw-r--r--src/core/hle/kernel/k_scheduler_lock.h11
-rw-r--r--src/core/hle/kernel/k_scoped_lock.h13
-rw-r--r--src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h4
-rw-r--r--src/core/hle/kernel/k_spin_lock.h6
-rw-r--r--src/core/hle/kernel/k_system_control.cpp42
-rw-r--r--src/core/hle/kernel/k_system_control.h18
-rw-r--r--src/core/hle/kernel/k_thread.h4
-rw-r--r--src/core/hle/kernel/k_trace.h12
-rw-r--r--src/core/hle/kernel/kernel.cpp326
-rw-r--r--src/core/hle/kernel/kernel.h2
-rw-r--r--src/core/hle/service/am/am.cpp22
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp2
-rw-r--r--src/core/hle/service/audio/audin_a.cpp8
-rw-r--r--src/core/hle/service/audio/audin_u.cpp14
-rw-r--r--src/core/hle/service/audio/audout_a.cpp12
-rw-r--r--src/core/hle/service/audio/audout_u.cpp6
-rw-r--r--src/core/hle/service/audio/audrec_a.cpp4
-rw-r--r--src/core/hle/service/audio/audrec_u.cpp7
-rw-r--r--src/core/hle/service/audio/audren_a.cpp12
-rw-r--r--src/core/hle/service/audio/audren_u.cpp6
-rw-r--r--src/core/hle/service/audio/audren_u.h2
-rw-r--r--src/core/hle/service/audio/codecctl.cpp26
-rw-r--r--src/core/hle/service/bcat/module.cpp2
-rw-r--r--src/core/hle/service/bpc/bpc.cpp4
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp19
-rw-r--r--src/core/hle/service/btm/btm.cpp1
-rw-r--r--src/core/hle/service/caps/caps_a.cpp1
-rw-r--r--src/core/hle/service/caps/caps_u.cpp1
-rw-r--r--src/core/hle/service/erpt/erpt.cpp7
-rw-r--r--src/core/hle/service/friend/friend.cpp14
-rw-r--r--src/core/hle/service/glue/arp.cpp11
-rw-r--r--src/core/hle/service/glue/arp.h2
-rw-r--r--src/core/hle/service/glue/bgtc.cpp27
-rw-r--r--src/core/hle/service/glue/bgtc.h8
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/npad.h2
-rw-r--r--src/core/hle/service/hid/hid.cpp106
-rw-r--r--src/core/hle/service/hid/hid.h1
-rw-r--r--src/core/hle/service/hid/xcd.cpp2
-rw-r--r--src/core/hle/service/ldr/ldr.cpp32
-rw-r--r--src/core/hle/service/nim/nim.cpp99
-rw-r--r--src/core/hle/service/npns/npns.cpp3
-rw-r--r--src/core/hle/service/ns/ns.cpp41
-rw-r--r--src/core/hle/service/ns/pl_u.cpp4
-rw-r--r--src/core/hle/service/olsc/olsc.cpp1
-rw-r--r--src/core/hle/service/pcie/pcie.cpp2
-rw-r--r--src/core/hle/service/pctl/module.cpp3
-rw-r--r--src/core/hle/service/service.cpp6
-rw-r--r--src/core/hle/service/set/set_sys.cpp6
-rw-r--r--src/core/hle/service/sm/sm.cpp9
-rw-r--r--src/core/hle/service/sockets/ethc.cpp1
-rw-r--r--src/core/hle/service/sockets/nsd.cpp1
-rw-r--r--src/core/hle/service/sockets/sfdnsres.cpp4
-rw-r--r--src/core/hle/service/spl/spl.cpp3
-rw-r--r--src/core/hle/service/time/time_zone_service.cpp1
-rw-r--r--src/core/hle/service/usb/usb.cpp42
-rw-r--r--src/core/hle/service/vi/vi.cpp8
-rw-r--r--src/core/hle/service/wlan/wlan.cpp7
-rw-r--r--src/core/settings.h1
-rw-r--r--src/video_core/gpu.cpp4
-rw-r--r--src/video_core/gpu.h4
-rw-r--r--src/video_core/gpu_thread.cpp62
-rw-r--r--src/video_core/gpu_thread.h15
-rw-r--r--src/yuzu/configuration/config.cpp1
-rw-r--r--src/yuzu/configuration/configure_debug.cpp2
-rw-r--r--src/yuzu/configuration/configure_debug.ui22
88 files changed, 2703 insertions, 365 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 66931ac97..9f8dafa3b 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -110,6 +110,7 @@ add_library(common STATIC
110 cityhash.h 110 cityhash.h
111 common_funcs.h 111 common_funcs.h
112 common_paths.h 112 common_paths.h
113 common_sizes.h
113 common_types.h 114 common_types.h
114 concepts.h 115 concepts.h
115 div_ceil.h 116 div_ceil.h
diff --git a/src/common/common_sizes.h b/src/common/common_sizes.h
new file mode 100644
index 000000000..7e9fd968b
--- /dev/null
+++ b/src/common/common_sizes.h
@@ -0,0 +1,43 @@
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 <limits>
8
9#include "common/common_types.h"
10
11namespace Common {
12
13enum : u64 {
14 Size_1_KB = 0x400ULL,
15 Size_64_KB = 64ULL * Size_1_KB,
16 Size_128_KB = 128ULL * Size_1_KB,
17 Size_1_MB = 0x100000ULL,
18 Size_2_MB = 2ULL * Size_1_MB,
19 Size_4_MB = 4ULL * Size_1_MB,
20 Size_5_MB = 5ULL * Size_1_MB,
21 Size_14_MB = 14ULL * Size_1_MB,
22 Size_32_MB = 32ULL * Size_1_MB,
23 Size_33_MB = 33ULL * Size_1_MB,
24 Size_128_MB = 128ULL * Size_1_MB,
25 Size_448_MB = 448ULL * Size_1_MB,
26 Size_507_MB = 507ULL * Size_1_MB,
27 Size_562_MB = 562ULL * Size_1_MB,
28 Size_1554_MB = 1554ULL * Size_1_MB,
29 Size_2048_MB = 2048ULL * Size_1_MB,
30 Size_2193_MB = 2193ULL * Size_1_MB,
31 Size_3285_MB = 3285ULL * Size_1_MB,
32 Size_4916_MB = 4916ULL * Size_1_MB,
33 Size_1_GB = 0x40000000ULL,
34 Size_2_GB = 2ULL * Size_1_GB,
35 Size_4_GB = 4ULL * Size_1_GB,
36 Size_6_GB = 6ULL * Size_1_GB,
37 Size_8_GB = 8ULL * Size_1_GB,
38 Size_64_GB = 64ULL * Size_1_GB,
39 Size_512_GB = 512ULL * Size_1_GB,
40 Size_Invalid = std::numeric_limits<u64>::max(),
41};
42
43} // namespace Common
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 2d4d2e9e7..4575df24d 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -212,6 +212,7 @@ void DebuggerBackend::Write(const Entry& entry) {
212 SUB(Service, ARP) \ 212 SUB(Service, ARP) \
213 SUB(Service, BCAT) \ 213 SUB(Service, BCAT) \
214 SUB(Service, BPC) \ 214 SUB(Service, BPC) \
215 SUB(Service, BGTC) \
215 SUB(Service, BTDRV) \ 216 SUB(Service, BTDRV) \
216 SUB(Service, BTM) \ 217 SUB(Service, BTM) \
217 SUB(Service, Capture) \ 218 SUB(Service, Capture) \
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 835894918..3d7b7dab7 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -66,6 +66,7 @@ enum class Class : ClassType {
66 Service_ARP, ///< The ARP service 66 Service_ARP, ///< The ARP service
67 Service_Audio, ///< The Audio (Audio control) service 67 Service_Audio, ///< The Audio (Audio control) service
68 Service_BCAT, ///< The BCAT service 68 Service_BCAT, ///< The BCAT service
69 Service_BGTC, ///< The BGTC (Background Task Controller) service
69 Service_BPC, ///< The BPC service 70 Service_BPC, ///< The BPC service
70 Service_BTDRV, ///< The Bluetooth driver service 71 Service_BTDRV, ///< The Bluetooth driver service
71 Service_BTM, ///< The BTM service 72 Service_BTM, ///< The BTM service
diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h
index a4647314a..ad04df8ca 100644
--- a/src/common/threadsafe_queue.h
+++ b/src/common/threadsafe_queue.h
@@ -83,11 +83,15 @@ public:
83 return true; 83 return true;
84 } 84 }
85 85
86 T PopWait() { 86 void Wait() {
87 if (Empty()) { 87 if (Empty()) {
88 std::unique_lock lock{cv_mutex}; 88 std::unique_lock lock{cv_mutex};
89 cv.wait(lock, [this]() { return !Empty(); }); 89 cv.wait(lock, [this]() { return !Empty(); });
90 } 90 }
91 }
92
93 T PopWait() {
94 Wait();
91 T t; 95 T t;
92 Pop(t); 96 Pop(t);
93 return t; 97 return t;
@@ -156,6 +160,10 @@ public:
156 return spsc_queue.Pop(t); 160 return spsc_queue.Pop(t);
157 } 161 }
158 162
163 void Wait() {
164 spsc_queue.Wait();
165 }
166
159 T PopWait() { 167 T PopWait() {
160 return spsc_queue.PopWait(); 168 return spsc_queue.PopWait();
161 } 169 }
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index e51a19e2d..167ee13f3 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -141,6 +141,9 @@ add_library(core STATIC
141 hardware_interrupt_manager.h 141 hardware_interrupt_manager.h
142 hle/ipc.h 142 hle/ipc.h
143 hle/ipc_helpers.h 143 hle/ipc_helpers.h
144 hle/kernel/board/nintendo/nx/k_system_control.cpp
145 hle/kernel/board/nintendo/nx/k_system_control.h
146 hle/kernel/board/nintendo/nx/secure_monitor.h
144 hle/kernel/client_port.cpp 147 hle/kernel/client_port.cpp
145 hle/kernel/client_port.h 148 hle/kernel/client_port.h
146 hle/kernel/client_session.cpp 149 hle/kernel/client_session.cpp
@@ -169,9 +172,13 @@ add_library(core STATIC
169 hle/kernel/k_memory_block.h 172 hle/kernel/k_memory_block.h
170 hle/kernel/k_memory_block_manager.cpp 173 hle/kernel/k_memory_block_manager.cpp
171 hle/kernel/k_memory_block_manager.h 174 hle/kernel/k_memory_block_manager.h
175 hle/kernel/k_memory_layout.cpp
176 hle/kernel/k_memory_layout.board.nintendo_nx.cpp
172 hle/kernel/k_memory_layout.h 177 hle/kernel/k_memory_layout.h
173 hle/kernel/k_memory_manager.cpp 178 hle/kernel/k_memory_manager.cpp
174 hle/kernel/k_memory_manager.h 179 hle/kernel/k_memory_manager.h
180 hle/kernel/k_memory_region.h
181 hle/kernel/k_memory_region_type.h
175 hle/kernel/k_page_bitmap.h 182 hle/kernel/k_page_bitmap.h
176 hle/kernel/k_page_heap.cpp 183 hle/kernel/k_page_heap.cpp
177 hle/kernel/k_page_heap.h 184 hle/kernel/k_page_heap.h
@@ -196,11 +203,11 @@ add_library(core STATIC
196 hle/kernel/k_spin_lock.h 203 hle/kernel/k_spin_lock.h
197 hle/kernel/k_synchronization_object.cpp 204 hle/kernel/k_synchronization_object.cpp
198 hle/kernel/k_synchronization_object.h 205 hle/kernel/k_synchronization_object.h
199 hle/kernel/k_system_control.cpp
200 hle/kernel/k_system_control.h 206 hle/kernel/k_system_control.h
201 hle/kernel/k_thread.cpp 207 hle/kernel/k_thread.cpp
202 hle/kernel/k_thread.h 208 hle/kernel/k_thread.h
203 hle/kernel/k_thread_queue.h 209 hle/kernel/k_thread_queue.h
210 hle/kernel/k_trace.h
204 hle/kernel/k_writable_event.cpp 211 hle/kernel/k_writable_event.cpp
205 hle/kernel/k_writable_event.h 212 hle/kernel/k_writable_event.h
206 hle/kernel/kernel.cpp 213 hle/kernel/kernel.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 305f56ff1..56b47e671 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -296,7 +296,7 @@ struct System::Impl {
296 exit_lock = false; 296 exit_lock = false;
297 297
298 if (gpu_core) { 298 if (gpu_core) {
299 gpu_core->WaitIdle(); 299 gpu_core->ShutDown();
300 } 300 }
301 301
302 services.reset(); 302 services.reset();
diff --git a/src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc b/src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc
new file mode 100644
index 000000000..857b512ba
--- /dev/null
+++ b/src/core/hle/kernel/arch/arm64/k_memory_region_device_types.inc
@@ -0,0 +1,20 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// All architectures must define NumArchitectureDeviceRegions.
6constexpr inline const auto NumArchitectureDeviceRegions = 3;
7
8constexpr inline const auto KMemoryRegionType_Uart =
9 KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 0);
10constexpr inline const auto KMemoryRegionType_InterruptCpuInterface =
11 KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 1)
12 .SetAttribute(KMemoryRegionAttr_NoUserMap);
13constexpr inline const auto KMemoryRegionType_InterruptDistributor =
14 KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 2)
15 .SetAttribute(KMemoryRegionAttr_NoUserMap);
16static_assert(KMemoryRegionType_Uart.GetValue() == (0x1D));
17static_assert(KMemoryRegionType_InterruptCpuInterface.GetValue() ==
18 (0x2D | KMemoryRegionAttr_NoUserMap));
19static_assert(KMemoryRegionType_InterruptDistributor.GetValue() ==
20 (0x4D | KMemoryRegionAttr_NoUserMap));
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc b/src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc
new file mode 100644
index 000000000..58d6c0b16
--- /dev/null
+++ b/src/core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc
@@ -0,0 +1,52 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5// All architectures must define NumBoardDeviceRegions.
6constexpr inline const auto NumBoardDeviceRegions = 6;
7// UNUSED: .Derive(NumBoardDeviceRegions, 0);
8constexpr inline const auto KMemoryRegionType_MemoryController =
9 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 1)
10 .SetAttribute(KMemoryRegionAttr_NoUserMap);
11constexpr inline const auto KMemoryRegionType_MemoryController1 =
12 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 2)
13 .SetAttribute(KMemoryRegionAttr_NoUserMap);
14constexpr inline const auto KMemoryRegionType_MemoryController0 =
15 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 3)
16 .SetAttribute(KMemoryRegionAttr_NoUserMap);
17constexpr inline const auto KMemoryRegionType_PowerManagementController =
18 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 4).DeriveTransition();
19constexpr inline const auto KMemoryRegionType_LegacyLpsDevices =
20 KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 5);
21static_assert(KMemoryRegionType_MemoryController.GetValue() ==
22 (0x55 | KMemoryRegionAttr_NoUserMap));
23static_assert(KMemoryRegionType_MemoryController1.GetValue() ==
24 (0x65 | KMemoryRegionAttr_NoUserMap));
25static_assert(KMemoryRegionType_MemoryController0.GetValue() ==
26 (0x95 | KMemoryRegionAttr_NoUserMap));
27static_assert(KMemoryRegionType_PowerManagementController.GetValue() == (0x1A5));
28
29static_assert(KMemoryRegionType_LegacyLpsDevices.GetValue() == 0xC5);
30
31constexpr inline const auto NumLegacyLpsDevices = 7;
32constexpr inline const auto KMemoryRegionType_LegacyLpsExceptionVectors =
33 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 0);
34constexpr inline const auto KMemoryRegionType_LegacyLpsIram =
35 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 1);
36constexpr inline const auto KMemoryRegionType_LegacyLpsFlowController =
37 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 2);
38constexpr inline const auto KMemoryRegionType_LegacyLpsPrimaryICtlr =
39 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 3);
40constexpr inline const auto KMemoryRegionType_LegacyLpsSemaphore =
41 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 4);
42constexpr inline const auto KMemoryRegionType_LegacyLpsAtomics =
43 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 5);
44constexpr inline const auto KMemoryRegionType_LegacyLpsClkRst =
45 KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 6);
46static_assert(KMemoryRegionType_LegacyLpsExceptionVectors.GetValue() == 0x3C5);
47static_assert(KMemoryRegionType_LegacyLpsIram.GetValue() == 0x5C5);
48static_assert(KMemoryRegionType_LegacyLpsFlowController.GetValue() == 0x6C5);
49static_assert(KMemoryRegionType_LegacyLpsPrimaryICtlr.GetValue() == 0x9C5);
50static_assert(KMemoryRegionType_LegacyLpsSemaphore.GetValue() == 0xAC5);
51static_assert(KMemoryRegionType_LegacyLpsAtomics.GetValue() == 0xCC5);
52static_assert(KMemoryRegionType_LegacyLpsClkRst.GetValue() == 0x11C5);
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
new file mode 100644
index 000000000..86472b5ce
--- /dev/null
+++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
@@ -0,0 +1,164 @@
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 <random>
6
7#include "common/common_sizes.h"
8#include "core/hle/kernel/board/nintendo/nx/k_system_control.h"
9#include "core/hle/kernel/board/nintendo/nx/secure_monitor.h"
10#include "core/hle/kernel/k_trace.h"
11
12namespace Kernel::Board::Nintendo::Nx {
13
14namespace impl {
15
16constexpr const std::size_t RequiredNonSecureSystemMemorySizeVi = 0x2238 * 4 * 1024;
17constexpr const std::size_t RequiredNonSecureSystemMemorySizeNvservices = 0x710 * 4 * 1024;
18constexpr const std::size_t RequiredNonSecureSystemMemorySizeMisc = 0x80 * 4 * 1024;
19
20} // namespace impl
21
22constexpr const std::size_t RequiredNonSecureSystemMemorySize =
23 impl::RequiredNonSecureSystemMemorySizeVi + impl::RequiredNonSecureSystemMemorySizeNvservices +
24 impl::RequiredNonSecureSystemMemorySizeMisc;
25
26namespace {
27
28u32 GetMemoryModeForInit() {
29 return 0x01;
30}
31
32u32 GetMemorySizeForInit() {
33 return 0;
34}
35
36Smc::MemoryArrangement GetMemoryArrangeForInit() {
37 switch (GetMemoryModeForInit() & 0x3F) {
38 case 0x01:
39 default:
40 return Smc::MemoryArrangement_4GB;
41 case 0x02:
42 return Smc::MemoryArrangement_4GBForAppletDev;
43 case 0x03:
44 return Smc::MemoryArrangement_4GBForSystemDev;
45 case 0x11:
46 return Smc::MemoryArrangement_6GB;
47 case 0x12:
48 return Smc::MemoryArrangement_6GBForAppletDev;
49 case 0x21:
50 return Smc::MemoryArrangement_8GB;
51 }
52}
53} // namespace
54
55// Initialization.
56size_t KSystemControl::Init::GetIntendedMemorySize() {
57 switch (GetMemorySizeForInit()) {
58 case Smc::MemorySize_4GB:
59 default: // All invalid modes should go to 4GB.
60 return Common::Size_4_GB;
61 case Smc::MemorySize_6GB:
62 return Common::Size_6_GB;
63 case Smc::MemorySize_8GB:
64 return Common::Size_8_GB;
65 }
66}
67
68PAddr KSystemControl::Init::GetKernelPhysicalBaseAddress(u64 base_address) {
69 return base_address;
70}
71
72bool KSystemControl::Init::ShouldIncreaseThreadResourceLimit() {
73 return true;
74}
75
76std::size_t KSystemControl::Init::GetApplicationPoolSize() {
77 // Get the base pool size.
78 const size_t base_pool_size = []() -> size_t {
79 switch (GetMemoryArrangeForInit()) {
80 case Smc::MemoryArrangement_4GB:
81 default:
82 return Common::Size_3285_MB;
83 case Smc::MemoryArrangement_4GBForAppletDev:
84 return Common::Size_2048_MB;
85 case Smc::MemoryArrangement_4GBForSystemDev:
86 return Common::Size_3285_MB;
87 case Smc::MemoryArrangement_6GB:
88 return Common::Size_4916_MB;
89 case Smc::MemoryArrangement_6GBForAppletDev:
90 return Common::Size_3285_MB;
91 case Smc::MemoryArrangement_8GB:
92 return Common::Size_4916_MB;
93 }
94 }();
95
96 // Return (possibly) adjusted size.
97 return base_pool_size;
98}
99
100size_t KSystemControl::Init::GetAppletPoolSize() {
101 // Get the base pool size.
102 const size_t base_pool_size = []() -> size_t {
103 switch (GetMemoryArrangeForInit()) {
104 case Smc::MemoryArrangement_4GB:
105 default:
106 return Common::Size_507_MB;
107 case Smc::MemoryArrangement_4GBForAppletDev:
108 return Common::Size_1554_MB;
109 case Smc::MemoryArrangement_4GBForSystemDev:
110 return Common::Size_448_MB;
111 case Smc::MemoryArrangement_6GB:
112 return Common::Size_562_MB;
113 case Smc::MemoryArrangement_6GBForAppletDev:
114 return Common::Size_2193_MB;
115 case Smc::MemoryArrangement_8GB:
116 return Common::Size_2193_MB;
117 }
118 }();
119
120 // Return (possibly) adjusted size.
121 constexpr size_t ExtraSystemMemoryForAtmosphere = Common::Size_33_MB;
122 return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
123}
124
125size_t KSystemControl::Init::GetMinimumNonSecureSystemPoolSize() {
126 // Verify that our minimum is at least as large as Nintendo's.
127 constexpr size_t MinimumSize = RequiredNonSecureSystemMemorySize;
128 static_assert(MinimumSize >= 0x29C8000);
129
130 return MinimumSize;
131}
132
133namespace {
134template <typename F>
135u64 GenerateUniformRange(u64 min, u64 max, F f) {
136 // Handle the case where the difference is too large to represent.
137 if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) {
138 return f();
139 }
140
141 // Iterate until we get a value in range.
142 const u64 range_size = ((max + 1) - min);
143 const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
144 while (true) {
145 if (const u64 rnd = f(); rnd < effective_max) {
146 return min + (rnd % range_size);
147 }
148 }
149}
150
151} // Anonymous namespace
152
153u64 KSystemControl::GenerateRandomU64() {
154 static std::random_device device;
155 static std::mt19937 gen(device());
156 static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
157 return distribution(gen);
158}
159
160u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) {
161 return GenerateUniformRange(min, max, GenerateRandomU64);
162}
163
164} // namespace Kernel::Board::Nintendo::Nx
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.h b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
new file mode 100644
index 000000000..52f230ced
--- /dev/null
+++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
@@ -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#pragma once
6
7#include "common/common_types.h"
8
9namespace Kernel::Board::Nintendo::Nx {
10
11class KSystemControl {
12public:
13 class Init {
14 public:
15 // Initialization.
16 static std::size_t GetIntendedMemorySize();
17 static PAddr GetKernelPhysicalBaseAddress(u64 base_address);
18 static bool ShouldIncreaseThreadResourceLimit();
19 static std::size_t GetApplicationPoolSize();
20 static std::size_t GetAppletPoolSize();
21 static std::size_t GetMinimumNonSecureSystemPoolSize();
22 };
23
24 static u64 GenerateRandomRange(u64 min, u64 max);
25 static u64 GenerateRandomU64();
26};
27
28} // namespace Kernel::Board::Nintendo::Nx
diff --git a/src/core/hle/kernel/board/nintendo/nx/secure_monitor.h b/src/core/hle/kernel/board/nintendo/nx/secure_monitor.h
new file mode 100644
index 000000000..0c366b252
--- /dev/null
+++ b/src/core/hle/kernel/board/nintendo/nx/secure_monitor.h
@@ -0,0 +1,26 @@
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::Board::Nintendo::Nx::Smc {
10
11enum MemorySize {
12 MemorySize_4GB = 0,
13 MemorySize_6GB = 1,
14 MemorySize_8GB = 2,
15};
16
17enum MemoryArrangement {
18 MemoryArrangement_4GB = 0,
19 MemoryArrangement_4GBForAppletDev = 1,
20 MemoryArrangement_4GBForSystemDev = 2,
21 MemoryArrangement_6GB = 3,
22 MemoryArrangement_6GBForAppletDev = 4,
23 MemoryArrangement_8GB = 5,
24};
25
26} // namespace Kernel::Board::Nintendo::Nx::Smc
diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp
index 24944d15b..c7549f7a2 100644
--- a/src/core/hle/kernel/k_address_space_info.cpp
+++ b/src/core/hle/kernel/k_address_space_info.cpp
@@ -5,45 +5,34 @@
5#include <array> 5#include <array>
6 6
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/common_sizes.h"
8#include "core/hle/kernel/k_address_space_info.h" 9#include "core/hle/kernel/k_address_space_info.h"
9 10
10namespace Kernel { 11namespace Kernel {
11 12
12namespace { 13namespace {
13 14
14enum : u64 {
15 Size_1_MB = 0x100000,
16 Size_2_MB = 2 * Size_1_MB,
17 Size_128_MB = 128 * Size_1_MB,
18 Size_1_GB = 0x40000000,
19 Size_2_GB = 2 * Size_1_GB,
20 Size_4_GB = 4 * Size_1_GB,
21 Size_6_GB = 6 * Size_1_GB,
22 Size_64_GB = 64 * Size_1_GB,
23 Size_512_GB = 512 * Size_1_GB,
24 Invalid = std::numeric_limits<u64>::max(),
25};
26
27// clang-format off 15// clang-format off
28constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{ 16constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{
29 { .bit_width = 32, .address = Size_2_MB , .size = Size_1_GB - Size_2_MB , .type = KAddressSpaceInfo::Type::MapSmall, }, 17 { .bit_width = 32, .address = Common::Size_2_MB , .size = Common::Size_1_GB - Common::Size_2_MB , .type = KAddressSpaceInfo::Type::MapSmall, },
30 { .bit_width = 32, .address = Size_1_GB , .size = Size_4_GB - Size_1_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, 18 { .bit_width = 32, .address = Common::Size_1_GB , .size = Common::Size_4_GB - Common::Size_1_GB , .type = KAddressSpaceInfo::Type::MapLarge, },
31 { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = KAddressSpaceInfo::Type::Heap, }, 19 { .bit_width = 32, .address = Common::Size_Invalid, .size = Common::Size_1_GB , .type = KAddressSpaceInfo::Type::Alias, },
32 { .bit_width = 32, .address = Invalid , .size = Size_1_GB , .type = KAddressSpaceInfo::Type::Alias, }, 20 { .bit_width = 32, .address = Common::Size_Invalid, .size = Common::Size_1_GB , .type = KAddressSpaceInfo::Type::Heap, },
33 { .bit_width = 36, .address = Size_128_MB, .size = Size_2_GB - Size_128_MB, .type = KAddressSpaceInfo::Type::MapSmall, }, 21 { .bit_width = 36, .address = Common::Size_128_MB , .size = Common::Size_2_GB - Common::Size_128_MB, .type = KAddressSpaceInfo::Type::MapSmall, },
34 { .bit_width = 36, .address = Size_2_GB , .size = Size_64_GB - Size_2_GB , .type = KAddressSpaceInfo::Type::MapLarge, }, 22 { .bit_width = 36, .address = Common::Size_2_GB , .size = Common::Size_64_GB - Common::Size_2_GB , .type = KAddressSpaceInfo::Type::MapLarge, },
35 { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, 23 { .bit_width = 36, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, },
36 { .bit_width = 36, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Alias, }, 24 { .bit_width = 36, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Alias, },
37 { .bit_width = 39, .address = Size_128_MB, .size = Size_512_GB - Size_128_MB, .type = KAddressSpaceInfo::Type::Map39Bit, }, 25 { .bit_width = 39, .address = Common::Size_128_MB , .size = Common::Size_512_GB - Common::Size_128_MB, .type = KAddressSpaceInfo::Type::Map39Bit, },
38 { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = KAddressSpaceInfo::Type::MapSmall }, 26 { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_64_GB , .type = KAddressSpaceInfo::Type::MapSmall },
39 { .bit_width = 39, .address = Invalid , .size = Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, }, 27 { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, },
40 { .bit_width = 39, .address = Invalid , .size = Size_64_GB , .type = KAddressSpaceInfo::Type::Alias, }, 28 { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_64_GB , .type = KAddressSpaceInfo::Type::Alias, },
41 { .bit_width = 39, .address = Invalid , .size = Size_2_GB , .type = KAddressSpaceInfo::Type::Stack, }, 29 { .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_2_GB , .type = KAddressSpaceInfo::Type::Stack, },
42}}; 30}};
43// clang-format on 31// clang-format on
44 32
45constexpr bool IsAllowedIndexForAddress(std::size_t index) { 33constexpr bool IsAllowedIndexForAddress(std::size_t index) {
46 return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Invalid; 34 return index < AddressSpaceInfos.size() &&
35 AddressSpaceInfos[index].address != Common::Size_Invalid;
47} 36}
48 37
49using IndexArray = 38using IndexArray =
diff --git a/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp b/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp
new file mode 100644
index 000000000..a78551291
--- /dev/null
+++ b/src/core/hle/kernel/k_memory_layout.board.nintendo_nx.cpp
@@ -0,0 +1,199 @@
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 "common/alignment.h"
6#include "core/hle/kernel/k_memory_layout.h"
7#include "core/hle/kernel/k_memory_manager.h"
8#include "core/hle/kernel/k_system_control.h"
9#include "core/hle/kernel/k_trace.h"
10
11namespace Kernel {
12
13namespace {
14
15constexpr size_t CarveoutAlignment = 0x20000;
16constexpr size_t CarveoutSizeMax = (512ULL * 1024 * 1024) - CarveoutAlignment;
17
18bool SetupPowerManagementControllerMemoryRegion(KMemoryLayout& memory_layout) {
19 // Above firmware 2.0.0, the PMC is not mappable.
20 return memory_layout.GetPhysicalMemoryRegionTree().Insert(
21 0x7000E000, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap) &&
22 memory_layout.GetPhysicalMemoryRegionTree().Insert(
23 0x7000E400, 0xC00,
24 KMemoryRegionType_PowerManagementController | KMemoryRegionAttr_NoUserMap);
25}
26
27void InsertPoolPartitionRegionIntoBothTrees(KMemoryLayout& memory_layout, size_t start, size_t size,
28 KMemoryRegionType phys_type,
29 KMemoryRegionType virt_type, u32& cur_attr) {
30 const u32 attr = cur_attr++;
31 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(start, size,
32 static_cast<u32>(phys_type), attr));
33 const KMemoryRegion* phys = memory_layout.GetPhysicalMemoryRegionTree().FindByTypeAndAttribute(
34 static_cast<u32>(phys_type), attr);
35 ASSERT(phys != nullptr);
36 ASSERT(phys->GetEndAddress() != 0);
37 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(phys->GetPairAddress(), size,
38 static_cast<u32>(virt_type), attr));
39}
40
41} // namespace
42
43namespace Init {
44
45void SetupDevicePhysicalMemoryRegions(KMemoryLayout& memory_layout) {
46 ASSERT(SetupPowerManagementControllerMemoryRegion(memory_layout));
47 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
48 0x70019000, 0x1000, KMemoryRegionType_MemoryController | KMemoryRegionAttr_NoUserMap));
49 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
50 0x7001C000, 0x1000, KMemoryRegionType_MemoryController0 | KMemoryRegionAttr_NoUserMap));
51 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
52 0x7001D000, 0x1000, KMemoryRegionType_MemoryController1 | KMemoryRegionAttr_NoUserMap));
53 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
54 0x50040000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
55 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
56 0x50041000, 0x1000,
57 KMemoryRegionType_InterruptDistributor | KMemoryRegionAttr_ShouldKernelMap));
58 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
59 0x50042000, 0x1000,
60 KMemoryRegionType_InterruptCpuInterface | KMemoryRegionAttr_ShouldKernelMap));
61 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
62 0x50043000, 0x1D000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
63
64 // Map IRAM unconditionally, to support debug-logging-to-iram build config.
65 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
66 0x40000000, 0x40000, KMemoryRegionType_LegacyLpsIram | KMemoryRegionAttr_ShouldKernelMap));
67
68 // Above firmware 2.0.0, prevent mapping the bpmp exception vectors or the ipatch region.
69 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
70 0x6000F000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
71 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
72 0x6001DC00, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap));
73}
74
75void SetupDramPhysicalMemoryRegions(KMemoryLayout& memory_layout) {
76 const size_t intended_memory_size = KSystemControl::Init::GetIntendedMemorySize();
77 const PAddr physical_memory_base_address =
78 KSystemControl::Init::GetKernelPhysicalBaseAddress(DramPhysicalAddress);
79
80 // Insert blocks into the tree.
81 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
82 physical_memory_base_address, intended_memory_size, KMemoryRegionType_Dram));
83 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
84 physical_memory_base_address, ReservedEarlyDramSize, KMemoryRegionType_DramReservedEarly));
85
86 // Insert the KTrace block at the end of Dram, if KTrace is enabled.
87 static_assert(!IsKTraceEnabled || KTraceBufferSize > 0);
88 if constexpr (IsKTraceEnabled) {
89 const PAddr ktrace_buffer_phys_addr =
90 physical_memory_base_address + intended_memory_size - KTraceBufferSize;
91 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
92 ktrace_buffer_phys_addr, KTraceBufferSize, KMemoryRegionType_KernelTraceBuffer));
93 }
94}
95
96void SetupPoolPartitionMemoryRegions(KMemoryLayout& memory_layout) {
97 // Start by identifying the extents of the DRAM memory region.
98 const auto dram_extents = memory_layout.GetMainMemoryPhysicalExtents();
99 ASSERT(dram_extents.GetEndAddress() != 0);
100
101 // Determine the end of the pool region.
102 const u64 pool_end = dram_extents.GetEndAddress() - KTraceBufferSize;
103
104 // Find the start of the kernel DRAM region.
105 const KMemoryRegion* kernel_dram_region =
106 memory_layout.GetPhysicalMemoryRegionTree().FindFirstDerived(
107 KMemoryRegionType_DramKernelBase);
108 ASSERT(kernel_dram_region != nullptr);
109
110 const u64 kernel_dram_start = kernel_dram_region->GetAddress();
111 ASSERT(Common::IsAligned(kernel_dram_start, CarveoutAlignment));
112
113 // Find the start of the pool partitions region.
114 const KMemoryRegion* pool_partitions_region =
115 memory_layout.GetPhysicalMemoryRegionTree().FindByTypeAndAttribute(
116 KMemoryRegionType_DramPoolPartition, 0);
117 ASSERT(pool_partitions_region != nullptr);
118 const u64 pool_partitions_start = pool_partitions_region->GetAddress();
119
120 // Setup the pool partition layouts.
121 // On 5.0.0+, setup modern 4-pool-partition layout.
122
123 // Get Application and Applet pool sizes.
124 const size_t application_pool_size = KSystemControl::Init::GetApplicationPoolSize();
125 const size_t applet_pool_size = KSystemControl::Init::GetAppletPoolSize();
126 const size_t unsafe_system_pool_min_size =
127 KSystemControl::Init::GetMinimumNonSecureSystemPoolSize();
128
129 // Decide on starting addresses for our pools.
130 const u64 application_pool_start = pool_end - application_pool_size;
131 const u64 applet_pool_start = application_pool_start - applet_pool_size;
132 const u64 unsafe_system_pool_start = std::min(
133 kernel_dram_start + CarveoutSizeMax,
134 Common::AlignDown(applet_pool_start - unsafe_system_pool_min_size, CarveoutAlignment));
135 const size_t unsafe_system_pool_size = applet_pool_start - unsafe_system_pool_start;
136
137 // We want to arrange application pool depending on where the middle of dram is.
138 const u64 dram_midpoint = (dram_extents.GetAddress() + dram_extents.GetEndAddress()) / 2;
139 u32 cur_pool_attr = 0;
140 size_t total_overhead_size = 0;
141 if (dram_extents.GetEndAddress() <= dram_midpoint || dram_midpoint <= application_pool_start) {
142 InsertPoolPartitionRegionIntoBothTrees(
143 memory_layout, application_pool_start, application_pool_size,
144 KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool,
145 cur_pool_attr);
146 total_overhead_size +=
147 KMemoryManager::CalculateManagementOverheadSize(application_pool_size);
148 } else {
149 const size_t first_application_pool_size = dram_midpoint - application_pool_start;
150 const size_t second_application_pool_size =
151 application_pool_start + application_pool_size - dram_midpoint;
152 InsertPoolPartitionRegionIntoBothTrees(
153 memory_layout, application_pool_start, first_application_pool_size,
154 KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool,
155 cur_pool_attr);
156 InsertPoolPartitionRegionIntoBothTrees(
157 memory_layout, dram_midpoint, second_application_pool_size,
158 KMemoryRegionType_DramApplicationPool, KMemoryRegionType_VirtualDramApplicationPool,
159 cur_pool_attr);
160 total_overhead_size +=
161 KMemoryManager::CalculateManagementOverheadSize(first_application_pool_size);
162 total_overhead_size +=
163 KMemoryManager::CalculateManagementOverheadSize(second_application_pool_size);
164 }
165
166 // Insert the applet pool.
167 InsertPoolPartitionRegionIntoBothTrees(memory_layout, applet_pool_start, applet_pool_size,
168 KMemoryRegionType_DramAppletPool,
169 KMemoryRegionType_VirtualDramAppletPool, cur_pool_attr);
170 total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(applet_pool_size);
171
172 // Insert the nonsecure system pool.
173 InsertPoolPartitionRegionIntoBothTrees(
174 memory_layout, unsafe_system_pool_start, unsafe_system_pool_size,
175 KMemoryRegionType_DramSystemNonSecurePool, KMemoryRegionType_VirtualDramSystemNonSecurePool,
176 cur_pool_attr);
177 total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(unsafe_system_pool_size);
178
179 // Insert the pool management region.
180 total_overhead_size += KMemoryManager::CalculateManagementOverheadSize(
181 (unsafe_system_pool_start - pool_partitions_start) - total_overhead_size);
182 const u64 pool_management_start = unsafe_system_pool_start - total_overhead_size;
183 const size_t pool_management_size = total_overhead_size;
184 u32 pool_management_attr = 0;
185 InsertPoolPartitionRegionIntoBothTrees(
186 memory_layout, pool_management_start, pool_management_size,
187 KMemoryRegionType_DramPoolManagement, KMemoryRegionType_VirtualDramPoolManagement,
188 pool_management_attr);
189
190 // Insert the system pool.
191 const u64 system_pool_size = pool_management_start - pool_partitions_start;
192 InsertPoolPartitionRegionIntoBothTrees(memory_layout, pool_partitions_start, system_pool_size,
193 KMemoryRegionType_DramSystemPool,
194 KMemoryRegionType_VirtualDramSystemPool, cur_pool_attr);
195}
196
197} // namespace Init
198
199} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_layout.cpp b/src/core/hle/kernel/k_memory_layout.cpp
new file mode 100644
index 000000000..fb1e2435f
--- /dev/null
+++ b/src/core/hle/kernel/k_memory_layout.cpp
@@ -0,0 +1,166 @@
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 <array>
6
7#include "common/alignment.h"
8#include "core/hle/kernel/k_memory_layout.h"
9#include "core/hle/kernel/k_system_control.h"
10
11namespace Kernel {
12
13namespace {
14
15template <typename... Args>
16KMemoryRegion* AllocateRegion(KMemoryRegionAllocator& memory_region_allocator, Args&&... args) {
17 return memory_region_allocator.Allocate(std::forward<Args>(args)...);
18}
19
20} // namespace
21
22KMemoryRegionTree::KMemoryRegionTree(KMemoryRegionAllocator& memory_region_allocator_)
23 : memory_region_allocator{memory_region_allocator_} {}
24
25void KMemoryRegionTree::InsertDirectly(u64 address, u64 last_address, u32 attr, u32 type_id) {
26 this->insert(*AllocateRegion(memory_region_allocator, address, last_address, attr, type_id));
27}
28
29bool KMemoryRegionTree::Insert(u64 address, size_t size, u32 type_id, u32 new_attr, u32 old_attr) {
30 // Locate the memory region that contains the address.
31 KMemoryRegion* found = this->FindModifiable(address);
32
33 // We require that the old attr is correct.
34 if (found->GetAttributes() != old_attr) {
35 return false;
36 }
37
38 // We further require that the region can be split from the old region.
39 const u64 inserted_region_end = address + size;
40 const u64 inserted_region_last = inserted_region_end - 1;
41 if (found->GetLastAddress() < inserted_region_last) {
42 return false;
43 }
44
45 // Further, we require that the type id is a valid transformation.
46 if (!found->CanDerive(type_id)) {
47 return false;
48 }
49
50 // Cache information from the region before we remove it.
51 const u64 old_address = found->GetAddress();
52 const u64 old_last = found->GetLastAddress();
53 const u64 old_pair = found->GetPairAddress();
54 const u32 old_type = found->GetType();
55
56 // Erase the existing region from the tree.
57 this->erase(this->iterator_to(*found));
58
59 // Insert the new region into the tree.
60 if (old_address == address) {
61 // Reuse the old object for the new region, if we can.
62 found->Reset(address, inserted_region_last, old_pair, new_attr, type_id);
63 this->insert(*found);
64 } else {
65 // If we can't re-use, adjust the old region.
66 found->Reset(old_address, address - 1, old_pair, old_attr, old_type);
67 this->insert(*found);
68
69 // Insert a new region for the split.
70 const u64 new_pair = (old_pair != std::numeric_limits<u64>::max())
71 ? old_pair + (address - old_address)
72 : old_pair;
73 this->insert(*AllocateRegion(memory_region_allocator, address, inserted_region_last,
74 new_pair, new_attr, type_id));
75 }
76
77 // If we need to insert a region after the region, do so.
78 if (old_last != inserted_region_last) {
79 const u64 after_pair = (old_pair != std::numeric_limits<u64>::max())
80 ? old_pair + (inserted_region_end - old_address)
81 : old_pair;
82 this->insert(*AllocateRegion(memory_region_allocator, inserted_region_end, old_last,
83 after_pair, old_attr, old_type));
84 }
85
86 return true;
87}
88
89VAddr KMemoryRegionTree::GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id) {
90 // We want to find the total extents of the type id.
91 const auto extents = this->GetDerivedRegionExtents(static_cast<KMemoryRegionType>(type_id));
92
93 // Ensure that our alignment is correct.
94 ASSERT(Common::IsAligned(extents.GetAddress(), alignment));
95
96 const u64 first_address = extents.GetAddress();
97 const u64 last_address = extents.GetLastAddress();
98
99 const u64 first_index = first_address / alignment;
100 const u64 last_index = last_address / alignment;
101
102 while (true) {
103 const u64 candidate =
104 KSystemControl::GenerateRandomRange(first_index, last_index) * alignment;
105
106 // Ensure that the candidate doesn't overflow with the size.
107 if (!(candidate < candidate + size)) {
108 continue;
109 }
110
111 const u64 candidate_last = candidate + size - 1;
112
113 // Ensure that the candidate fits within the region.
114 if (candidate_last > last_address) {
115 continue;
116 }
117
118 // Locate the candidate region, and ensure it fits and has the correct type id.
119 if (const auto& candidate_region = *this->Find(candidate);
120 !(candidate_last <= candidate_region.GetLastAddress() &&
121 candidate_region.GetType() == type_id)) {
122 continue;
123 }
124
125 return candidate;
126 }
127}
128
129KMemoryLayout::KMemoryLayout()
130 : virtual_tree{memory_region_allocator}, physical_tree{memory_region_allocator},
131 virtual_linear_tree{memory_region_allocator}, physical_linear_tree{memory_region_allocator} {}
132
133void KMemoryLayout::InitializeLinearMemoryRegionTrees(PAddr aligned_linear_phys_start,
134 VAddr linear_virtual_start) {
135 // Set static differences.
136 linear_phys_to_virt_diff = linear_virtual_start - aligned_linear_phys_start;
137 linear_virt_to_phys_diff = aligned_linear_phys_start - linear_virtual_start;
138
139 // Initialize linear trees.
140 for (auto& region : GetPhysicalMemoryRegionTree()) {
141 if (region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) {
142 GetPhysicalLinearMemoryRegionTree().InsertDirectly(
143 region.GetAddress(), region.GetLastAddress(), region.GetAttributes(),
144 region.GetType());
145 }
146 }
147
148 for (auto& region : GetVirtualMemoryRegionTree()) {
149 if (region.IsDerivedFrom(KMemoryRegionType_Dram)) {
150 GetVirtualLinearMemoryRegionTree().InsertDirectly(
151 region.GetAddress(), region.GetLastAddress(), region.GetAttributes(),
152 region.GetType());
153 }
154 }
155}
156
157size_t KMemoryLayout::GetResourceRegionSizeForInit() {
158 // Calculate resource region size based on whether we allow extra threads.
159 const bool use_extra_resources = KSystemControl::Init::ShouldIncreaseThreadResourceLimit();
160 size_t resource_region_size =
161 KernelResourceSize + (use_extra_resources ? KernelSlabHeapAdditionalSize : 0);
162
163 return resource_region_size;
164}
165
166} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_layout.h b/src/core/hle/kernel/k_memory_layout.h
index 0821d2d8c..288642d9a 100644
--- a/src/core/hle/kernel/k_memory_layout.h
+++ b/src/core/hle/kernel/k_memory_layout.h
@@ -1,23 +1,69 @@
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#pragma once 5#pragma once
6 6
7#include <utility>
8
9#include "common/alignment.h"
10#include "common/common_sizes.h"
7#include "common/common_types.h" 11#include "common/common_types.h"
8#include "core/device_memory.h" 12#include "core/device_memory.h"
13#include "core/hle/kernel/k_memory_region.h"
14#include "core/hle/kernel/k_memory_region_type.h"
15#include "core/hle/kernel/memory_types.h"
9 16
10namespace Kernel { 17namespace Kernel {
11 18
12constexpr std::size_t KernelAslrAlignment = 2 * 1024 * 1024; 19constexpr std::size_t L1BlockSize = Common::Size_1_GB;
20constexpr std::size_t L2BlockSize = Common::Size_2_MB;
21
22constexpr std::size_t GetMaximumOverheadSize(std::size_t size) {
23 return (Common::DivideUp(size, L1BlockSize) + Common::DivideUp(size, L2BlockSize)) * PageSize;
24}
25
26constexpr std::size_t MainMemorySize = Common::Size_4_GB;
27constexpr std::size_t MainMemorySizeMax = Common::Size_8_GB;
28
29constexpr std::size_t ReservedEarlyDramSize = 0x60000;
30constexpr std::size_t DramPhysicalAddress = 0x80000000;
31
32constexpr std::size_t KernelAslrAlignment = Common::Size_2_MB;
13constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39; 33constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39;
14constexpr std::size_t KernelPhysicalAddressSpaceWidth = 1ULL << 48; 34constexpr std::size_t KernelPhysicalAddressSpaceWidth = 1ULL << 48;
35
15constexpr std::size_t KernelVirtualAddressSpaceBase = 0ULL - KernelVirtualAddressSpaceWidth; 36constexpr std::size_t KernelVirtualAddressSpaceBase = 0ULL - KernelVirtualAddressSpaceWidth;
16constexpr std::size_t KernelVirtualAddressSpaceEnd = 37constexpr std::size_t KernelVirtualAddressSpaceEnd =
17 KernelVirtualAddressSpaceBase + (KernelVirtualAddressSpaceWidth - KernelAslrAlignment); 38 KernelVirtualAddressSpaceBase + (KernelVirtualAddressSpaceWidth - KernelAslrAlignment);
18constexpr std::size_t KernelVirtualAddressSpaceLast = KernelVirtualAddressSpaceEnd - 1; 39constexpr std::size_t KernelVirtualAddressSpaceLast = KernelVirtualAddressSpaceEnd - 1ULL;
19constexpr std::size_t KernelVirtualAddressSpaceSize = 40constexpr std::size_t KernelVirtualAddressSpaceSize =
20 KernelVirtualAddressSpaceEnd - KernelVirtualAddressSpaceBase; 41 KernelVirtualAddressSpaceEnd - KernelVirtualAddressSpaceBase;
42constexpr std::size_t KernelVirtualAddressCodeBase = KernelVirtualAddressSpaceBase;
43constexpr std::size_t KernelVirtualAddressCodeSize = 0x62000;
44constexpr std::size_t KernelVirtualAddressCodeEnd =
45 KernelVirtualAddressCodeBase + KernelVirtualAddressCodeSize;
46
47constexpr std::size_t KernelPhysicalAddressSpaceBase = 0ULL;
48constexpr std::size_t KernelPhysicalAddressSpaceEnd =
49 KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceWidth;
50constexpr std::size_t KernelPhysicalAddressSpaceLast = KernelPhysicalAddressSpaceEnd - 1ULL;
51constexpr std::size_t KernelPhysicalAddressSpaceSize =
52 KernelPhysicalAddressSpaceEnd - KernelPhysicalAddressSpaceBase;
53constexpr std::size_t KernelPhysicalAddressCodeBase = DramPhysicalAddress + ReservedEarlyDramSize;
54
55constexpr std::size_t KernelPageTableHeapSize = GetMaximumOverheadSize(MainMemorySizeMax);
56constexpr std::size_t KernelInitialPageHeapSize = Common::Size_128_KB;
57
58constexpr std::size_t KernelSlabHeapDataSize = Common::Size_5_MB;
59constexpr std::size_t KernelSlabHeapGapsSize = Common::Size_2_MB - Common::Size_64_KB;
60constexpr std::size_t KernelSlabHeapSize = KernelSlabHeapDataSize + KernelSlabHeapGapsSize;
61
62// NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x860.
63constexpr std::size_t KernelSlabHeapAdditionalSize = 0x68000ULL;
64
65constexpr std::size_t KernelResourceSize =
66 KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize;
21 67
22constexpr bool IsKernelAddressKey(VAddr key) { 68constexpr bool IsKernelAddressKey(VAddr key) {
23 return KernelVirtualAddressSpaceBase <= key && key <= KernelVirtualAddressSpaceLast; 69 return KernelVirtualAddressSpaceBase <= key && key <= KernelVirtualAddressSpaceLast;
@@ -27,64 +73,327 @@ constexpr bool IsKernelAddress(VAddr address) {
27 return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd; 73 return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd;
28} 74}
29 75
30class KMemoryRegion final { 76class KMemoryLayout final {
31 friend class KMemoryLayout;
32
33public: 77public:
34 constexpr PAddr StartAddress() const { 78 KMemoryLayout();
35 return start_address; 79
80 KMemoryRegionTree& GetVirtualMemoryRegionTree() {
81 return virtual_tree;
82 }
83 const KMemoryRegionTree& GetVirtualMemoryRegionTree() const {
84 return virtual_tree;
85 }
86 KMemoryRegionTree& GetPhysicalMemoryRegionTree() {
87 return physical_tree;
88 }
89 const KMemoryRegionTree& GetPhysicalMemoryRegionTree() const {
90 return physical_tree;
91 }
92 KMemoryRegionTree& GetVirtualLinearMemoryRegionTree() {
93 return virtual_linear_tree;
94 }
95 const KMemoryRegionTree& GetVirtualLinearMemoryRegionTree() const {
96 return virtual_linear_tree;
97 }
98 KMemoryRegionTree& GetPhysicalLinearMemoryRegionTree() {
99 return physical_linear_tree;
100 }
101 const KMemoryRegionTree& GetPhysicalLinearMemoryRegionTree() const {
102 return physical_linear_tree;
103 }
104
105 VAddr GetLinearVirtualAddress(PAddr address) const {
106 return address + linear_phys_to_virt_diff;
107 }
108 PAddr GetLinearPhysicalAddress(VAddr address) const {
109 return address + linear_virt_to_phys_diff;
110 }
111
112 const KMemoryRegion* FindVirtual(VAddr address) const {
113 return Find(address, GetVirtualMemoryRegionTree());
114 }
115 const KMemoryRegion* FindPhysical(PAddr address) const {
116 return Find(address, GetPhysicalMemoryRegionTree());
117 }
118
119 const KMemoryRegion* FindVirtualLinear(VAddr address) const {
120 return Find(address, GetVirtualLinearMemoryRegionTree());
121 }
122 const KMemoryRegion* FindPhysicalLinear(PAddr address) const {
123 return Find(address, GetPhysicalLinearMemoryRegionTree());
124 }
125
126 VAddr GetMainStackTopAddress(s32 core_id) const {
127 return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscMainStack);
128 }
129 VAddr GetIdleStackTopAddress(s32 core_id) const {
130 return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscIdleStack);
131 }
132 VAddr GetExceptionStackTopAddress(s32 core_id) const {
133 return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscExceptionStack);
134 }
135
136 VAddr GetSlabRegionAddress() const {
137 return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelSlab))
138 .GetAddress();
139 }
140
141 const KMemoryRegion& GetDeviceRegion(KMemoryRegionType type) const {
142 return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(type));
143 }
144 PAddr GetDevicePhysicalAddress(KMemoryRegionType type) const {
145 return GetDeviceRegion(type).GetAddress();
146 }
147 VAddr GetDeviceVirtualAddress(KMemoryRegionType type) const {
148 return GetDeviceRegion(type).GetPairAddress();
149 }
150
151 const KMemoryRegion& GetPoolManagementRegion() const {
152 return Dereference(
153 GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramPoolManagement));
154 }
155 const KMemoryRegion& GetPageTableHeapRegion() const {
156 return Dereference(
157 GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelPtHeap));
158 }
159 const KMemoryRegion& GetKernelStackRegion() const {
160 return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelStack));
161 }
162 const KMemoryRegion& GetTempRegion() const {
163 return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelTemp));
164 }
165
166 const KMemoryRegion& GetKernelTraceBufferRegion() const {
167 return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(
168 KMemoryRegionType_VirtualDramKernelTraceBuffer));
169 }
170
171 const KMemoryRegion& GetVirtualLinearRegion(VAddr address) const {
172 return Dereference(FindVirtualLinear(address));
173 }
174
175 const KMemoryRegion* GetPhysicalKernelTraceBufferRegion() const {
176 return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_KernelTraceBuffer);
177 }
178 const KMemoryRegion* GetPhysicalOnMemoryBootImageRegion() const {
179 return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_OnMemoryBootImage);
180 }
181 const KMemoryRegion* GetPhysicalDTBRegion() const {
182 return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_DTB);
183 }
184
185 bool IsHeapPhysicalAddress(const KMemoryRegion*& region, PAddr address) const {
186 return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(),
187 KMemoryRegionType_DramUserPool);
188 }
189 bool IsHeapVirtualAddress(const KMemoryRegion*& region, VAddr address) const {
190 return IsTypedAddress(region, address, GetVirtualLinearMemoryRegionTree(),
191 KMemoryRegionType_VirtualDramUserPool);
192 }
193
194 bool IsHeapPhysicalAddress(const KMemoryRegion*& region, PAddr address, size_t size) const {
195 return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(),
196 KMemoryRegionType_DramUserPool);
197 }
198 bool IsHeapVirtualAddress(const KMemoryRegion*& region, VAddr address, size_t size) const {
199 return IsTypedAddress(region, address, size, GetVirtualLinearMemoryRegionTree(),
200 KMemoryRegionType_VirtualDramUserPool);
201 }
202
203 bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region, PAddr address) const {
204 return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(),
205 static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped));
206 }
207 bool IsLinearMappedPhysicalAddress(const KMemoryRegion*& region, PAddr address,
208 size_t size) const {
209 return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(),
210 static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped));
211 }
212
213 std::pair<size_t, size_t> GetTotalAndKernelMemorySizes() const {
214 size_t total_size = 0, kernel_size = 0;
215 for (const auto& region : GetPhysicalMemoryRegionTree()) {
216 if (region.IsDerivedFrom(KMemoryRegionType_Dram)) {
217 total_size += region.GetSize();
218 if (!region.IsDerivedFrom(KMemoryRegionType_DramUserPool)) {
219 kernel_size += region.GetSize();
220 }
221 }
222 }
223 return std::make_pair(total_size, kernel_size);
224 }
225
226 void InitializeLinearMemoryRegionTrees(PAddr aligned_linear_phys_start,
227 VAddr linear_virtual_start);
228 static size_t GetResourceRegionSizeForInit();
229
230 auto GetKernelRegionExtents() const {
231 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Kernel);
232 }
233 auto GetKernelCodeRegionExtents() const {
234 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelCode);
235 }
236 auto GetKernelStackRegionExtents() const {
237 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelStack);
238 }
239 auto GetKernelMiscRegionExtents() const {
240 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelMisc);
241 }
242 auto GetKernelSlabRegionExtents() const {
243 return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelSlab);
244 }
245
246 auto GetLinearRegionPhysicalExtents() const {
247 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
248 KMemoryRegionAttr_LinearMapped);
249 }
250
251 auto GetLinearRegionVirtualExtents() const {
252 const auto physical = GetLinearRegionPhysicalExtents();
253 return KMemoryRegion(GetLinearVirtualAddress(physical.GetAddress()),
254 GetLinearVirtualAddress(physical.GetLastAddress()), 0,
255 KMemoryRegionType_None);
256 }
257
258 auto GetMainMemoryPhysicalExtents() const {
259 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Dram);
260 }
261 auto GetCarveoutRegionExtents() const {
262 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
263 KMemoryRegionAttr_CarveoutProtected);
264 }
265
266 auto GetKernelRegionPhysicalExtents() const {
267 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
268 KMemoryRegionType_DramKernelBase);
269 }
270 auto GetKernelCodeRegionPhysicalExtents() const {
271 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
272 KMemoryRegionType_DramKernelCode);
273 }
274 auto GetKernelSlabRegionPhysicalExtents() const {
275 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
276 KMemoryRegionType_DramKernelSlab);
277 }
278 auto GetKernelPageTableHeapRegionPhysicalExtents() const {
279 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
280 KMemoryRegionType_DramKernelPtHeap);
281 }
282 auto GetKernelInitPageTableRegionPhysicalExtents() const {
283 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
284 KMemoryRegionType_DramKernelInitPt);
285 }
286
287 auto GetKernelPoolManagementRegionPhysicalExtents() const {
288 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
289 KMemoryRegionType_DramPoolManagement);
290 }
291 auto GetKernelPoolPartitionRegionPhysicalExtents() const {
292 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
293 KMemoryRegionType_DramPoolPartition);
294 }
295 auto GetKernelSystemPoolRegionPhysicalExtents() const {
296 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
297 KMemoryRegionType_DramSystemPool);
298 }
299 auto GetKernelSystemNonSecurePoolRegionPhysicalExtents() const {
300 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
301 KMemoryRegionType_DramSystemNonSecurePool);
302 }
303 auto GetKernelAppletPoolRegionPhysicalExtents() const {
304 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
305 KMemoryRegionType_DramAppletPool);
306 }
307 auto GetKernelApplicationPoolRegionPhysicalExtents() const {
308 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
309 KMemoryRegionType_DramApplicationPool);
36 } 310 }
37 311
38 constexpr PAddr EndAddress() const { 312 auto GetKernelTraceBufferRegionPhysicalExtents() const {
39 return end_address; 313 return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
314 KMemoryRegionType_KernelTraceBuffer);
40 } 315 }
41 316
42private: 317private:
43 constexpr KMemoryRegion() = default; 318 template <typename AddressType>
44 constexpr KMemoryRegion(PAddr start_address, PAddr end_address) 319 static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address,
45 : start_address{start_address}, end_address{end_address} {} 320 const KMemoryRegionTree& tree, KMemoryRegionType type) {
321 // Check if the cached region already contains the address.
322 if (region != nullptr && region->Contains(address)) {
323 return true;
324 }
46 325
47 const PAddr start_address{}; 326 // Find the containing region, and update the cache.
48 const PAddr end_address{}; 327 if (const KMemoryRegion* found = tree.Find(address);
49}; 328 found != nullptr && found->IsDerivedFrom(type)) {
329 region = found;
330 return true;
331 } else {
332 return false;
333 }
334 }
50 335
51class KMemoryLayout final { 336 template <typename AddressType>
52public: 337 static bool IsTypedAddress(const KMemoryRegion*& region, AddressType address, size_t size,
53 constexpr const KMemoryRegion& Application() const { 338 const KMemoryRegionTree& tree, KMemoryRegionType type) {
54 return application; 339 // Get the end of the checked region.
340 const u64 last_address = address + size - 1;
341
342 // Walk the tree to verify the region is correct.
343 const KMemoryRegion* cur =
344 (region != nullptr && region->Contains(address)) ? region : tree.Find(address);
345 while (cur != nullptr && cur->IsDerivedFrom(type)) {
346 if (last_address <= cur->GetLastAddress()) {
347 region = cur;
348 return true;
349 }
350
351 cur = cur->GetNext();
352 }
353 return false;
55 } 354 }
56 355
57 constexpr const KMemoryRegion& Applet() const { 356 template <typename AddressType>
58 return applet; 357 static const KMemoryRegion* Find(AddressType address, const KMemoryRegionTree& tree) {
358 return tree.Find(address);
59 } 359 }
60 360
61 constexpr const KMemoryRegion& System() const { 361 static KMemoryRegion& Dereference(KMemoryRegion* region) {
62 return system; 362 ASSERT(region != nullptr);
363 return *region;
63 } 364 }
64 365
65 static constexpr KMemoryLayout GetDefaultLayout() { 366 static const KMemoryRegion& Dereference(const KMemoryRegion* region) {
66 constexpr std::size_t application_size{0xcd500000}; 367 ASSERT(region != nullptr);
67 constexpr std::size_t applet_size{0x1fb00000}; 368 return *region;
68 constexpr PAddr application_start_address{Core::DramMemoryMap::End - application_size}; 369 }
69 constexpr PAddr application_end_address{Core::DramMemoryMap::End}; 370
70 constexpr PAddr applet_start_address{application_start_address - applet_size}; 371 VAddr GetStackTopAddress(s32 core_id, KMemoryRegionType type) const {
71 constexpr PAddr applet_end_address{applet_start_address + applet_size}; 372 const auto& region = Dereference(
72 constexpr PAddr system_start_address{Core::DramMemoryMap::SlabHeapEnd}; 373 GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id)));
73 constexpr PAddr system_end_address{applet_start_address}; 374 ASSERT(region.GetEndAddress() != 0);
74 return {application_start_address, application_end_address, applet_start_address, 375 return region.GetEndAddress();
75 applet_end_address, system_start_address, system_end_address};
76 } 376 }
77 377
78private: 378private:
79 constexpr KMemoryLayout(PAddr application_start_address, std::size_t application_size, 379 u64 linear_phys_to_virt_diff{};
80 PAddr applet_start_address, std::size_t applet_size, 380 u64 linear_virt_to_phys_diff{};
81 PAddr system_start_address, std::size_t system_size) 381 KMemoryRegionAllocator memory_region_allocator;
82 : application{application_start_address, application_size}, 382 KMemoryRegionTree virtual_tree;
83 applet{applet_start_address, applet_size}, system{system_start_address, system_size} {} 383 KMemoryRegionTree physical_tree;
84 384 KMemoryRegionTree virtual_linear_tree;
85 const KMemoryRegion application; 385 KMemoryRegionTree physical_linear_tree;
86 const KMemoryRegion applet;
87 const KMemoryRegion system;
88}; 386};
89 387
388namespace Init {
389
390// These should be generic, regardless of board.
391void SetupPoolPartitionMemoryRegions(KMemoryLayout& memory_layout);
392
393// These may be implemented in a board-specific manner.
394void SetupDevicePhysicalMemoryRegions(KMemoryLayout& memory_layout);
395void SetupDramPhysicalMemoryRegions(KMemoryLayout& memory_layout);
396
397} // namespace Init
398
90} // namespace Kernel 399} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp
index 9027602bf..aa71697b2 100644
--- a/src/core/hle/kernel/k_memory_manager.cpp
+++ b/src/core/hle/kernel/k_memory_manager.cpp
@@ -173,4 +173,16 @@ ResultCode KMemoryManager::Free(KPageLinkedList& page_list, std::size_t num_page
173 return RESULT_SUCCESS; 173 return RESULT_SUCCESS;
174} 174}
175 175
176std::size_t KMemoryManager::Impl::CalculateManagementOverheadSize(std::size_t region_size) {
177 const std::size_t ref_count_size = (region_size / PageSize) * sizeof(u16);
178 const std::size_t optimize_map_size =
179 (Common::AlignUp((region_size / PageSize), Common::BitSize<u64>()) /
180 Common::BitSize<u64>()) *
181 sizeof(u64);
182 const std::size_t manager_meta_size =
183 Common::AlignUp(optimize_map_size + ref_count_size, PageSize);
184 const std::size_t page_heap_size = KPageHeap::CalculateManagementOverheadSize(region_size);
185 return manager_meta_size + page_heap_size;
186}
187
176} // namespace Kernel 188} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_manager.h b/src/core/hle/kernel/k_memory_manager.h
index ae9f683b8..ac840b3d0 100644
--- a/src/core/hle/kernel/k_memory_manager.h
+++ b/src/core/hle/kernel/k_memory_manager.h
@@ -29,6 +29,10 @@ public:
29 29
30 Shift = 4, 30 Shift = 4,
31 Mask = (0xF << Shift), 31 Mask = (0xF << Shift),
32
33 // Aliases.
34 Unsafe = Application,
35 Secure = System,
32 }; 36 };
33 37
34 enum class Direction : u32 { 38 enum class Direction : u32 {
@@ -56,6 +60,10 @@ public:
56 static constexpr std::size_t MaxManagerCount = 10; 60 static constexpr std::size_t MaxManagerCount = 10;
57 61
58public: 62public:
63 static std::size_t CalculateManagementOverheadSize(std::size_t region_size) {
64 return Impl::CalculateManagementOverheadSize(region_size);
65 }
66
59 static constexpr u32 EncodeOption(Pool pool, Direction dir) { 67 static constexpr u32 EncodeOption(Pool pool, Direction dir) {
60 return (static_cast<u32>(pool) << static_cast<u32>(Pool::Shift)) | 68 return (static_cast<u32>(pool) << static_cast<u32>(Pool::Shift)) |
61 (static_cast<u32>(dir) << static_cast<u32>(Direction::Shift)); 69 (static_cast<u32>(dir) << static_cast<u32>(Direction::Shift));
@@ -86,6 +94,16 @@ private:
86 Pool pool{}; 94 Pool pool{};
87 95
88 public: 96 public:
97 static std::size_t CalculateManagementOverheadSize(std::size_t region_size);
98
99 static constexpr std::size_t CalculateOptimizedProcessOverheadSize(
100 std::size_t region_size) {
101 return (Common::AlignUp((region_size / PageSize), Common::BitSize<u64>()) /
102 Common::BitSize<u64>()) *
103 sizeof(u64);
104 }
105
106 public:
89 Impl() = default; 107 Impl() = default;
90 108
91 std::size_t Initialize(Pool new_pool, u64 start_address, u64 end_address); 109 std::size_t Initialize(Pool new_pool, u64 start_address, u64 end_address);
diff --git a/src/core/hle/kernel/k_memory_region.h b/src/core/hle/kernel/k_memory_region.h
new file mode 100644
index 000000000..a861c04ab
--- /dev/null
+++ b/src/core/hle/kernel/k_memory_region.h
@@ -0,0 +1,350 @@
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/assert.h"
8#include "common/common_types.h"
9#include "common/intrusive_red_black_tree.h"
10#include "core/hle/kernel/k_memory_region_type.h"
11
12namespace Kernel {
13
14class KMemoryRegionAllocator;
15
16class KMemoryRegion final : public Common::IntrusiveRedBlackTreeBaseNode<KMemoryRegion>,
17 NonCopyable {
18 friend class KMemoryRegionTree;
19
20public:
21 constexpr KMemoryRegion() = default;
22 constexpr KMemoryRegion(u64 address_, u64 last_address_)
23 : address{address_}, last_address{last_address_} {}
24 constexpr KMemoryRegion(u64 address_, u64 last_address_, u64 pair_address_, u32 attributes_,
25 u32 type_id_)
26 : address(address_), last_address(last_address_), pair_address(pair_address_),
27 attributes(attributes_), type_id(type_id_) {}
28 constexpr KMemoryRegion(u64 address_, u64 last_address_, u32 attributes_, u32 type_id_)
29 : KMemoryRegion(address_, last_address_, std::numeric_limits<u64>::max(), attributes_,
30 type_id_) {}
31
32 static constexpr int Compare(const KMemoryRegion& lhs, const KMemoryRegion& rhs) {
33 if (lhs.GetAddress() < rhs.GetAddress()) {
34 return -1;
35 } else if (lhs.GetAddress() <= rhs.GetLastAddress()) {
36 return 0;
37 } else {
38 return 1;
39 }
40 }
41
42private:
43 constexpr void Reset(u64 a, u64 la, u64 p, u32 r, u32 t) {
44 address = a;
45 pair_address = p;
46 last_address = la;
47 attributes = r;
48 type_id = t;
49 }
50
51public:
52 constexpr u64 GetAddress() const {
53 return address;
54 }
55
56 constexpr u64 GetPairAddress() const {
57 return pair_address;
58 }
59
60 constexpr u64 GetLastAddress() const {
61 return last_address;
62 }
63
64 constexpr u64 GetEndAddress() const {
65 return this->GetLastAddress() + 1;
66 }
67
68 constexpr size_t GetSize() const {
69 return this->GetEndAddress() - this->GetAddress();
70 }
71
72 constexpr u32 GetAttributes() const {
73 return attributes;
74 }
75
76 constexpr u32 GetType() const {
77 return type_id;
78 }
79
80 constexpr void SetType(u32 type) {
81 ASSERT(this->CanDerive(type));
82 type_id = type;
83 }
84
85 constexpr bool Contains(u64 address) const {
86 ASSERT(this->GetEndAddress() != 0);
87 return this->GetAddress() <= address && address <= this->GetLastAddress();
88 }
89
90 constexpr bool IsDerivedFrom(u32 type) const {
91 return (this->GetType() | type) == this->GetType();
92 }
93
94 constexpr bool HasTypeAttribute(u32 attr) const {
95 return (this->GetType() | attr) == this->GetType();
96 }
97
98 constexpr bool CanDerive(u32 type) const {
99 return (this->GetType() | type) == type;
100 }
101
102 constexpr void SetPairAddress(u64 a) {
103 pair_address = a;
104 }
105
106 constexpr void SetTypeAttribute(u32 attr) {
107 type_id |= attr;
108 }
109
110private:
111 u64 address{};
112 u64 last_address{};
113 u64 pair_address{};
114 u32 attributes{};
115 u32 type_id{};
116};
117
118class KMemoryRegionTree final : NonCopyable {
119public:
120 struct DerivedRegionExtents {
121 const KMemoryRegion* first_region{};
122 const KMemoryRegion* last_region{};
123
124 constexpr DerivedRegionExtents() = default;
125
126 constexpr u64 GetAddress() const {
127 return this->first_region->GetAddress();
128 }
129
130 constexpr u64 GetLastAddress() const {
131 return this->last_region->GetLastAddress();
132 }
133
134 constexpr u64 GetEndAddress() const {
135 return this->GetLastAddress() + 1;
136 }
137
138 constexpr size_t GetSize() const {
139 return this->GetEndAddress() - this->GetAddress();
140 }
141 };
142
143private:
144 using TreeType =
145 Common::IntrusiveRedBlackTreeBaseTraits<KMemoryRegion>::TreeType<KMemoryRegion>;
146
147public:
148 using value_type = TreeType::value_type;
149 using size_type = TreeType::size_type;
150 using difference_type = TreeType::difference_type;
151 using pointer = TreeType::pointer;
152 using const_pointer = TreeType::const_pointer;
153 using reference = TreeType::reference;
154 using const_reference = TreeType::const_reference;
155 using iterator = TreeType::iterator;
156 using const_iterator = TreeType::const_iterator;
157
158private:
159 TreeType m_tree{};
160 KMemoryRegionAllocator& memory_region_allocator;
161
162public:
163 explicit KMemoryRegionTree(KMemoryRegionAllocator& memory_region_allocator_);
164
165public:
166 KMemoryRegion* FindModifiable(u64 address) {
167 if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->end()) {
168 return std::addressof(*it);
169 } else {
170 return nullptr;
171 }
172 }
173
174 const KMemoryRegion* Find(u64 address) const {
175 if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->cend()) {
176 return std::addressof(*it);
177 } else {
178 return nullptr;
179 }
180 }
181
182 const KMemoryRegion* FindByType(KMemoryRegionType type_id) const {
183 for (auto it = this->cbegin(); it != this->cend(); ++it) {
184 if (it->GetType() == static_cast<u32>(type_id)) {
185 return std::addressof(*it);
186 }
187 }
188 return nullptr;
189 }
190
191 const KMemoryRegion* FindByTypeAndAttribute(u32 type_id, u32 attr) const {
192 for (auto it = this->cbegin(); it != this->cend(); ++it) {
193 if (it->GetType() == type_id && it->GetAttributes() == attr) {
194 return std::addressof(*it);
195 }
196 }
197 return nullptr;
198 }
199
200 const KMemoryRegion* FindFirstDerived(KMemoryRegionType type_id) const {
201 for (auto it = this->cbegin(); it != this->cend(); it++) {
202 if (it->IsDerivedFrom(type_id)) {
203 return std::addressof(*it);
204 }
205 }
206 return nullptr;
207 }
208
209 const KMemoryRegion* FindLastDerived(KMemoryRegionType type_id) const {
210 const KMemoryRegion* region = nullptr;
211 for (auto it = this->begin(); it != this->end(); it++) {
212 if (it->IsDerivedFrom(type_id)) {
213 region = std::addressof(*it);
214 }
215 }
216 return region;
217 }
218
219 DerivedRegionExtents GetDerivedRegionExtents(KMemoryRegionType type_id) const {
220 DerivedRegionExtents extents;
221
222 ASSERT(extents.first_region == nullptr);
223 ASSERT(extents.last_region == nullptr);
224
225 for (auto it = this->cbegin(); it != this->cend(); it++) {
226 if (it->IsDerivedFrom(type_id)) {
227 if (extents.first_region == nullptr) {
228 extents.first_region = std::addressof(*it);
229 }
230 extents.last_region = std::addressof(*it);
231 }
232 }
233
234 ASSERT(extents.first_region != nullptr);
235 ASSERT(extents.last_region != nullptr);
236
237 return extents;
238 }
239
240 DerivedRegionExtents GetDerivedRegionExtents(u32 type_id) const {
241 return GetDerivedRegionExtents(static_cast<KMemoryRegionType>(type_id));
242 }
243
244public:
245 void InsertDirectly(u64 address, u64 last_address, u32 attr = 0, u32 type_id = 0);
246 bool Insert(u64 address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0);
247
248 VAddr GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id);
249
250 VAddr GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id,
251 size_t guard_size) {
252 return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size;
253 }
254
255public:
256 // Iterator accessors.
257 iterator begin() {
258 return m_tree.begin();
259 }
260
261 const_iterator begin() const {
262 return m_tree.begin();
263 }
264
265 iterator end() {
266 return m_tree.end();
267 }
268
269 const_iterator end() const {
270 return m_tree.end();
271 }
272
273 const_iterator cbegin() const {
274 return this->begin();
275 }
276
277 const_iterator cend() const {
278 return this->end();
279 }
280
281 iterator iterator_to(reference ref) {
282 return m_tree.iterator_to(ref);
283 }
284
285 const_iterator iterator_to(const_reference ref) const {
286 return m_tree.iterator_to(ref);
287 }
288
289 // Content management.
290 bool empty() const {
291 return m_tree.empty();
292 }
293
294 reference back() {
295 return m_tree.back();
296 }
297
298 const_reference back() const {
299 return m_tree.back();
300 }
301
302 reference front() {
303 return m_tree.front();
304 }
305
306 const_reference front() const {
307 return m_tree.front();
308 }
309
310 iterator insert(reference ref) {
311 return m_tree.insert(ref);
312 }
313
314 iterator erase(iterator it) {
315 return m_tree.erase(it);
316 }
317
318 iterator find(const_reference ref) const {
319 return m_tree.find(ref);
320 }
321
322 iterator nfind(const_reference ref) const {
323 return m_tree.nfind(ref);
324 }
325};
326
327class KMemoryRegionAllocator final : NonCopyable {
328public:
329 static constexpr size_t MaxMemoryRegions = 200;
330
331 constexpr KMemoryRegionAllocator() = default;
332
333 template <typename... Args>
334 KMemoryRegion* Allocate(Args&&... args) {
335 // Ensure we stay within the bounds of our heap.
336 ASSERT(this->num_regions < MaxMemoryRegions);
337
338 // Create the new region.
339 KMemoryRegion* region = std::addressof(this->region_heap[this->num_regions++]);
340 new (region) KMemoryRegion(std::forward<Args>(args)...);
341
342 return region;
343 }
344
345private:
346 std::array<KMemoryRegion, MaxMemoryRegions> region_heap{};
347 size_t num_regions{};
348};
349
350} // namespace Kernel
diff --git a/src/core/hle/kernel/k_memory_region_type.h b/src/core/hle/kernel/k_memory_region_type.h
new file mode 100644
index 000000000..a05e66677
--- /dev/null
+++ b/src/core/hle/kernel/k_memory_region_type.h
@@ -0,0 +1,338 @@
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/bit_util.h"
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10
11#define ARCH_ARM64
12#define BOARD_NINTENDO_NX
13
14namespace Kernel {
15
16enum KMemoryRegionType : u32 {
17 KMemoryRegionAttr_CarveoutProtected = 0x04000000,
18 KMemoryRegionAttr_DidKernelMap = 0x08000000,
19 KMemoryRegionAttr_ShouldKernelMap = 0x10000000,
20 KMemoryRegionAttr_UserReadOnly = 0x20000000,
21 KMemoryRegionAttr_NoUserMap = 0x40000000,
22 KMemoryRegionAttr_LinearMapped = 0x80000000,
23};
24DECLARE_ENUM_FLAG_OPERATORS(KMemoryRegionType);
25
26namespace impl {
27
28constexpr size_t BitsForDeriveSparse(size_t n) {
29 return n + 1;
30}
31
32constexpr size_t BitsForDeriveDense(size_t n) {
33 size_t low = 0, high = 1;
34 for (size_t i = 0; i < n - 1; ++i) {
35 if ((++low) == high) {
36 ++high;
37 low = 0;
38 }
39 }
40 return high + 1;
41}
42
43class KMemoryRegionTypeValue {
44public:
45 using ValueType = std::underlying_type_t<KMemoryRegionType>;
46
47 constexpr KMemoryRegionTypeValue() = default;
48
49 constexpr operator KMemoryRegionType() const {
50 return static_cast<KMemoryRegionType>(m_value);
51 }
52
53 constexpr ValueType GetValue() const {
54 return m_value;
55 }
56
57 constexpr const KMemoryRegionTypeValue& Finalize() {
58 m_finalized = true;
59 return *this;
60 }
61
62 constexpr const KMemoryRegionTypeValue& SetSparseOnly() {
63 m_sparse_only = true;
64 return *this;
65 }
66
67 constexpr const KMemoryRegionTypeValue& SetDenseOnly() {
68 m_dense_only = true;
69 return *this;
70 }
71
72 constexpr KMemoryRegionTypeValue& SetAttribute(u32 attr) {
73 m_value |= attr;
74 return *this;
75 }
76
77 constexpr KMemoryRegionTypeValue DeriveInitial(
78 size_t i, size_t next = Common::BitSize<ValueType>()) const {
79 KMemoryRegionTypeValue new_type = *this;
80 new_type.m_value = (ValueType{1} << i);
81 new_type.m_next_bit = next;
82 return new_type;
83 }
84
85 constexpr KMemoryRegionTypeValue DeriveAttribute(u32 attr) const {
86 KMemoryRegionTypeValue new_type = *this;
87 new_type.m_value |= attr;
88 return new_type;
89 }
90
91 constexpr KMemoryRegionTypeValue DeriveTransition(size_t ofs = 0, size_t adv = 1) const {
92 KMemoryRegionTypeValue new_type = *this;
93 new_type.m_value |= (ValueType{1} << (m_next_bit + ofs));
94 new_type.m_next_bit += adv;
95 return new_type;
96 }
97
98 constexpr KMemoryRegionTypeValue DeriveSparse(size_t ofs, size_t n, size_t i) const {
99 KMemoryRegionTypeValue new_type = *this;
100 new_type.m_value |= (ValueType{1} << (m_next_bit + ofs));
101 new_type.m_value |= (ValueType{1} << (m_next_bit + ofs + 1 + i));
102 new_type.m_next_bit += ofs + n + 1;
103 return new_type;
104 }
105
106 constexpr KMemoryRegionTypeValue Derive(size_t n, size_t i) const {
107 size_t low = 0, high = 1;
108 for (size_t j = 0; j < i; ++j) {
109 if ((++low) == high) {
110 ++high;
111 low = 0;
112 }
113 }
114
115 KMemoryRegionTypeValue new_type = *this;
116 new_type.m_value |= (ValueType{1} << (m_next_bit + low));
117 new_type.m_value |= (ValueType{1} << (m_next_bit + high));
118 new_type.m_next_bit += BitsForDeriveDense(n);
119 return new_type;
120 }
121
122 constexpr KMemoryRegionTypeValue Advance(size_t n) const {
123 KMemoryRegionTypeValue new_type = *this;
124 new_type.m_next_bit += n;
125 return new_type;
126 }
127
128 constexpr bool IsAncestorOf(ValueType v) const {
129 return (m_value | v) == v;
130 }
131
132private:
133 constexpr KMemoryRegionTypeValue(ValueType v) : m_value(v) {}
134
135private:
136 ValueType m_value{};
137 size_t m_next_bit{};
138 bool m_finalized{};
139 bool m_sparse_only{};
140 bool m_dense_only{};
141};
142
143} // namespace impl
144
145constexpr auto KMemoryRegionType_None = impl::KMemoryRegionTypeValue();
146constexpr auto KMemoryRegionType_Kernel = KMemoryRegionType_None.DeriveInitial(0, 2);
147constexpr auto KMemoryRegionType_Dram = KMemoryRegionType_None.DeriveInitial(1, 2);
148static_assert(KMemoryRegionType_Kernel.GetValue() == 0x1);
149static_assert(KMemoryRegionType_Dram.GetValue() == 0x2);
150
151constexpr auto KMemoryRegionType_DramKernelBase =
152 KMemoryRegionType_Dram.DeriveSparse(0, 3, 0)
153 .SetAttribute(KMemoryRegionAttr_NoUserMap)
154 .SetAttribute(KMemoryRegionAttr_CarveoutProtected);
155constexpr auto KMemoryRegionType_DramReservedBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 1);
156constexpr auto KMemoryRegionType_DramHeapBase =
157 KMemoryRegionType_Dram.DeriveSparse(0, 3, 2).SetAttribute(KMemoryRegionAttr_LinearMapped);
158static_assert(KMemoryRegionType_DramKernelBase.GetValue() ==
159 (0xE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap));
160static_assert(KMemoryRegionType_DramReservedBase.GetValue() == (0x16));
161static_assert(KMemoryRegionType_DramHeapBase.GetValue() == (0x26 | KMemoryRegionAttr_LinearMapped));
162
163constexpr auto KMemoryRegionType_DramKernelCode =
164 KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 0);
165constexpr auto KMemoryRegionType_DramKernelSlab =
166 KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 1);
167constexpr auto KMemoryRegionType_DramKernelPtHeap =
168 KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 2).SetAttribute(
169 KMemoryRegionAttr_LinearMapped);
170constexpr auto KMemoryRegionType_DramKernelInitPt =
171 KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 3).SetAttribute(
172 KMemoryRegionAttr_LinearMapped);
173static_assert(KMemoryRegionType_DramKernelCode.GetValue() ==
174 (0xCE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap));
175static_assert(KMemoryRegionType_DramKernelSlab.GetValue() ==
176 (0x14E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap));
177static_assert(KMemoryRegionType_DramKernelPtHeap.GetValue() ==
178 (0x24E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap |
179 KMemoryRegionAttr_LinearMapped));
180static_assert(KMemoryRegionType_DramKernelInitPt.GetValue() ==
181 (0x44E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap |
182 KMemoryRegionAttr_LinearMapped));
183
184constexpr auto KMemoryRegionType_DramReservedEarly =
185 KMemoryRegionType_DramReservedBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap);
186static_assert(KMemoryRegionType_DramReservedEarly.GetValue() ==
187 (0x16 | KMemoryRegionAttr_NoUserMap));
188
189constexpr auto KMemoryRegionType_KernelTraceBuffer =
190 KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 0)
191 .SetAttribute(KMemoryRegionAttr_LinearMapped)
192 .SetAttribute(KMemoryRegionAttr_UserReadOnly);
193constexpr auto KMemoryRegionType_OnMemoryBootImage =
194 KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 1);
195constexpr auto KMemoryRegionType_DTB = KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 2);
196static_assert(KMemoryRegionType_KernelTraceBuffer.GetValue() ==
197 (0xD6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_UserReadOnly));
198static_assert(KMemoryRegionType_OnMemoryBootImage.GetValue() == 0x156);
199static_assert(KMemoryRegionType_DTB.GetValue() == 0x256);
200
201constexpr auto KMemoryRegionType_DramPoolPartition =
202 KMemoryRegionType_DramHeapBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap);
203static_assert(KMemoryRegionType_DramPoolPartition.GetValue() ==
204 (0x26 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
205
206constexpr auto KMemoryRegionType_DramPoolManagement =
207 KMemoryRegionType_DramPoolPartition.DeriveTransition(0, 2).DeriveTransition().SetAttribute(
208 KMemoryRegionAttr_CarveoutProtected);
209constexpr auto KMemoryRegionType_DramUserPool =
210 KMemoryRegionType_DramPoolPartition.DeriveTransition(1, 2).DeriveTransition();
211static_assert(KMemoryRegionType_DramPoolManagement.GetValue() ==
212 (0x166 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap |
213 KMemoryRegionAttr_CarveoutProtected));
214static_assert(KMemoryRegionType_DramUserPool.GetValue() ==
215 (0x1A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
216
217constexpr auto KMemoryRegionType_DramApplicationPool = KMemoryRegionType_DramUserPool.Derive(4, 0);
218constexpr auto KMemoryRegionType_DramAppletPool = KMemoryRegionType_DramUserPool.Derive(4, 1);
219constexpr auto KMemoryRegionType_DramSystemNonSecurePool =
220 KMemoryRegionType_DramUserPool.Derive(4, 2);
221constexpr auto KMemoryRegionType_DramSystemPool =
222 KMemoryRegionType_DramUserPool.Derive(4, 3).SetAttribute(KMemoryRegionAttr_CarveoutProtected);
223static_assert(KMemoryRegionType_DramApplicationPool.GetValue() ==
224 (0x7A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
225static_assert(KMemoryRegionType_DramAppletPool.GetValue() ==
226 (0xBA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
227static_assert(KMemoryRegionType_DramSystemNonSecurePool.GetValue() ==
228 (0xDA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
229static_assert(KMemoryRegionType_DramSystemPool.GetValue() ==
230 (0x13A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap |
231 KMemoryRegionAttr_CarveoutProtected));
232
233constexpr auto KMemoryRegionType_VirtualDramHeapBase = KMemoryRegionType_Dram.DeriveSparse(1, 3, 0);
234constexpr auto KMemoryRegionType_VirtualDramKernelPtHeap =
235 KMemoryRegionType_Dram.DeriveSparse(1, 3, 1);
236constexpr auto KMemoryRegionType_VirtualDramKernelTraceBuffer =
237 KMemoryRegionType_Dram.DeriveSparse(1, 3, 2);
238static_assert(KMemoryRegionType_VirtualDramHeapBase.GetValue() == 0x1A);
239static_assert(KMemoryRegionType_VirtualDramKernelPtHeap.GetValue() == 0x2A);
240static_assert(KMemoryRegionType_VirtualDramKernelTraceBuffer.GetValue() == 0x4A);
241
242constexpr auto KMemoryRegionType_VirtualDramKernelInitPt =
243 KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0);
244constexpr auto KMemoryRegionType_VirtualDramPoolManagement =
245 KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1);
246constexpr auto KMemoryRegionType_VirtualDramUserPool =
247 KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2);
248static_assert(KMemoryRegionType_VirtualDramKernelInitPt.GetValue() == 0x19A);
249static_assert(KMemoryRegionType_VirtualDramPoolManagement.GetValue() == 0x29A);
250static_assert(KMemoryRegionType_VirtualDramUserPool.GetValue() == 0x31A);
251
252// NOTE: For unknown reason, the pools are derived out-of-order here. It's worth eventually trying
253// to understand why Nintendo made this choice.
254// UNUSED: .Derive(6, 0);
255// UNUSED: .Derive(6, 1);
256constexpr auto KMemoryRegionType_VirtualDramAppletPool =
257 KMemoryRegionType_VirtualDramUserPool.Derive(6, 2);
258constexpr auto KMemoryRegionType_VirtualDramApplicationPool =
259 KMemoryRegionType_VirtualDramUserPool.Derive(6, 3);
260constexpr auto KMemoryRegionType_VirtualDramSystemNonSecurePool =
261 KMemoryRegionType_VirtualDramUserPool.Derive(6, 4);
262constexpr auto KMemoryRegionType_VirtualDramSystemPool =
263 KMemoryRegionType_VirtualDramUserPool.Derive(6, 5);
264static_assert(KMemoryRegionType_VirtualDramAppletPool.GetValue() == 0x1B1A);
265static_assert(KMemoryRegionType_VirtualDramApplicationPool.GetValue() == 0x271A);
266static_assert(KMemoryRegionType_VirtualDramSystemNonSecurePool.GetValue() == 0x2B1A);
267static_assert(KMemoryRegionType_VirtualDramSystemPool.GetValue() == 0x331A);
268
269constexpr auto KMemoryRegionType_ArchDeviceBase =
270 KMemoryRegionType_Kernel.DeriveTransition(0, 1).SetSparseOnly();
271constexpr auto KMemoryRegionType_BoardDeviceBase =
272 KMemoryRegionType_Kernel.DeriveTransition(0, 2).SetDenseOnly();
273static_assert(KMemoryRegionType_ArchDeviceBase.GetValue() == 0x5);
274static_assert(KMemoryRegionType_BoardDeviceBase.GetValue() == 0x5);
275
276#if defined(ARCH_ARM64)
277#include "core/hle/kernel/arch/arm64/k_memory_region_device_types.inc"
278#elif defined(ARCH_ARM)
279#error "Unimplemented"
280#else
281// Default to no architecture devices.
282constexpr auto NumArchitectureDeviceRegions = 0;
283#endif
284static_assert(NumArchitectureDeviceRegions >= 0);
285
286#if defined(BOARD_NINTENDO_NX)
287#include "core/hle/kernel/board/nintendo/nx/k_memory_region_device_types.inc"
288#else
289// Default to no board devices.
290constexpr auto NumBoardDeviceRegions = 0;
291#endif
292static_assert(NumBoardDeviceRegions >= 0);
293
294constexpr auto KMemoryRegionType_KernelCode = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 0);
295constexpr auto KMemoryRegionType_KernelStack = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 1);
296constexpr auto KMemoryRegionType_KernelMisc = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 2);
297constexpr auto KMemoryRegionType_KernelSlab = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 3);
298static_assert(KMemoryRegionType_KernelCode.GetValue() == 0x19);
299static_assert(KMemoryRegionType_KernelStack.GetValue() == 0x29);
300static_assert(KMemoryRegionType_KernelMisc.GetValue() == 0x49);
301static_assert(KMemoryRegionType_KernelSlab.GetValue() == 0x89);
302
303constexpr auto KMemoryRegionType_KernelMiscDerivedBase =
304 KMemoryRegionType_KernelMisc.DeriveTransition();
305static_assert(KMemoryRegionType_KernelMiscDerivedBase.GetValue() == 0x149);
306
307// UNUSED: .Derive(7, 0);
308constexpr auto KMemoryRegionType_KernelMiscMainStack =
309 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 1);
310constexpr auto KMemoryRegionType_KernelMiscMappedDevice =
311 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 2);
312constexpr auto KMemoryRegionType_KernelMiscExceptionStack =
313 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 3);
314constexpr auto KMemoryRegionType_KernelMiscUnknownDebug =
315 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 4);
316// UNUSED: .Derive(7, 5);
317constexpr auto KMemoryRegionType_KernelMiscIdleStack =
318 KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 6);
319static_assert(KMemoryRegionType_KernelMiscMainStack.GetValue() == 0xB49);
320static_assert(KMemoryRegionType_KernelMiscMappedDevice.GetValue() == 0xD49);
321static_assert(KMemoryRegionType_KernelMiscExceptionStack.GetValue() == 0x1349);
322static_assert(KMemoryRegionType_KernelMiscUnknownDebug.GetValue() == 0x1549);
323static_assert(KMemoryRegionType_KernelMiscIdleStack.GetValue() == 0x2349);
324
325constexpr auto KMemoryRegionType_KernelTemp = KMemoryRegionType_Kernel.Advance(2).Derive(2, 0);
326static_assert(KMemoryRegionType_KernelTemp.GetValue() == 0x31);
327
328constexpr KMemoryRegionType GetTypeForVirtualLinearMapping(u32 type_id) {
329 if (KMemoryRegionType_KernelTraceBuffer.IsAncestorOf(type_id)) {
330 return KMemoryRegionType_VirtualDramKernelTraceBuffer;
331 } else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) {
332 return KMemoryRegionType_VirtualDramKernelPtHeap;
333 } else {
334 return KMemoryRegionType_Dram;
335 }
336}
337
338} // namespace Kernel
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index e7de48476..d1df97305 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -62,7 +62,7 @@ void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedul
62} 62}
63 63
64u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { 64u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) {
65 std::scoped_lock lock{guard}; 65 KScopedSpinLock lk{guard};
66 if (KThread* prev_highest_thread = state.highest_priority_thread; 66 if (KThread* prev_highest_thread = state.highest_priority_thread;
67 prev_highest_thread != highest_thread) { 67 prev_highest_thread != highest_thread) {
68 if (prev_highest_thread != nullptr) { 68 if (prev_highest_thread != nullptr) {
@@ -637,11 +637,11 @@ void KScheduler::RescheduleCurrentCore() {
637 if (phys_core.IsInterrupted()) { 637 if (phys_core.IsInterrupted()) {
638 phys_core.ClearInterrupt(); 638 phys_core.ClearInterrupt();
639 } 639 }
640 guard.lock(); 640 guard.Lock();
641 if (state.needs_scheduling.load()) { 641 if (state.needs_scheduling.load()) {
642 Schedule(); 642 Schedule();
643 } else { 643 } else {
644 guard.unlock(); 644 guard.Unlock();
645 } 645 }
646} 646}
647 647
@@ -669,7 +669,7 @@ void KScheduler::Unload(KThread* thread) {
669 } else { 669 } else {
670 prev_thread = nullptr; 670 prev_thread = nullptr;
671 } 671 }
672 thread->context_guard.unlock(); 672 thread->context_guard.Unlock();
673 } 673 }
674} 674}
675 675
@@ -713,7 +713,7 @@ void KScheduler::ScheduleImpl() {
713 713
714 // If we're not actually switching thread, there's nothing to do. 714 // If we're not actually switching thread, there's nothing to do.
715 if (next_thread == current_thread.load()) { 715 if (next_thread == current_thread.load()) {
716 guard.unlock(); 716 guard.Unlock();
717 return; 717 return;
718 } 718 }
719 719
@@ -732,7 +732,7 @@ void KScheduler::ScheduleImpl() {
732 } else { 732 } else {
733 old_context = &idle_thread->GetHostContext(); 733 old_context = &idle_thread->GetHostContext();
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.
@@ -748,24 +748,24 @@ void KScheduler::OnSwitch(void* this_scheduler) {
748void KScheduler::SwitchToCurrent() { 748void KScheduler::SwitchToCurrent() {
749 while (true) { 749 while (true) {
750 { 750 {
751 std::scoped_lock lock{guard}; 751 KScopedSpinLock lk{guard};
752 current_thread.store(state.highest_priority_thread); 752 current_thread.store(state.highest_priority_thread);
753 state.needs_scheduling.store(false); 753 state.needs_scheduling.store(false);
754 } 754 }
755 const auto is_switch_pending = [this] { 755 const auto is_switch_pending = [this] {
756 std::scoped_lock lock{guard}; 756 KScopedSpinLock lk{guard};
757 return state.needs_scheduling.load(); 757 return state.needs_scheduling.load();
758 }; 758 };
759 do { 759 do {
760 auto next_thread = current_thread.load(); 760 auto next_thread = current_thread.load();
761 if (next_thread != nullptr) { 761 if (next_thread != nullptr) {
762 next_thread->context_guard.lock(); 762 next_thread->context_guard.Lock();
763 if (next_thread->GetRawState() != ThreadState::Runnable) { 763 if (next_thread->GetRawState() != ThreadState::Runnable) {
764 next_thread->context_guard.unlock(); 764 next_thread->context_guard.Unlock();
765 break; 765 break;
766 } 766 }
767 if (next_thread->GetActiveCore() != core_id) { 767 if (next_thread->GetActiveCore() != core_id) {
768 next_thread->context_guard.unlock(); 768 next_thread->context_guard.Unlock();
769 break; 769 break;
770 } 770 }
771 } 771 }
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h
index f595b9a5c..8e32865aa 100644
--- a/src/core/hle/kernel/k_scheduler.h
+++ b/src/core/hle/kernel/k_scheduler.h
@@ -2,19 +2,16 @@
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>
11 8
12#include "common/common_types.h" 9#include "common/common_types.h"
13#include "common/spin_lock.h"
14#include "core/hle/kernel/global_scheduler_context.h" 10#include "core/hle/kernel/global_scheduler_context.h"
15#include "core/hle/kernel/k_priority_queue.h" 11#include "core/hle/kernel/k_priority_queue.h"
16#include "core/hle/kernel/k_scheduler_lock.h" 12#include "core/hle/kernel/k_scheduler_lock.h"
17#include "core/hle/kernel/k_scoped_lock.h" 13#include "core/hle/kernel/k_scoped_lock.h"
14#include "core/hle/kernel/k_spin_lock.h"
18 15
19namespace Common { 16namespace Common {
20class Fiber; 17class Fiber;
@@ -195,12 +192,12 @@ private:
195 u64 last_context_switch_time{}; 192 u64 last_context_switch_time{};
196 const s32 core_id; 193 const s32 core_id;
197 194
198 Common::SpinLock guard{}; 195 KSpinLock guard{};
199}; 196};
200 197
201class KScopedSchedulerLock : KScopedLock<GlobalSchedulerContext::LockType> { 198class [[nodiscard]] KScopedSchedulerLock : KScopedLock<GlobalSchedulerContext::LockType> {
202public: 199public:
203 explicit KScopedSchedulerLock(KernelCore& kernel); 200 explicit KScopedSchedulerLock(KernelCore & kernel);
204 ~KScopedSchedulerLock(); 201 ~KScopedSchedulerLock();
205}; 202};
206 203
diff --git a/src/core/hle/kernel/k_scheduler_lock.h b/src/core/hle/kernel/k_scheduler_lock.h
index 169455d18..47e315555 100644
--- a/src/core/hle/kernel/k_scheduler_lock.h
+++ b/src/core/hle/kernel/k_scheduler_lock.h
@@ -2,14 +2,11 @@
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/assert.h" 7#include "common/assert.h"
11#include "common/spin_lock.h"
12#include "core/hardware_properties.h" 8#include "core/hardware_properties.h"
9#include "core/hle/kernel/k_spin_lock.h"
13#include "core/hle/kernel/k_thread.h" 10#include "core/hle/kernel/k_thread.h"
14#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
15 12
@@ -34,7 +31,7 @@ public:
34 } else { 31 } else {
35 // Otherwise, we want to disable scheduling and acquire the spinlock. 32 // Otherwise, we want to disable scheduling and acquire the spinlock.
36 SchedulerType::DisableScheduling(kernel); 33 SchedulerType::DisableScheduling(kernel);
37 spin_lock.lock(); 34 spin_lock.Lock();
38 35
39 // For debug, ensure that our state is valid. 36 // For debug, ensure that our state is valid.
40 ASSERT(lock_count == 0); 37 ASSERT(lock_count == 0);
@@ -58,7 +55,7 @@ public:
58 55
59 // Note that we no longer hold the lock, and unlock the spinlock. 56 // Note that we no longer hold the lock, and unlock the spinlock.
60 owner_thread = nullptr; 57 owner_thread = nullptr;
61 spin_lock.unlock(); 58 spin_lock.Unlock();
62 59
63 // Enable scheduling, and perform a rescheduling operation. 60 // Enable scheduling, and perform a rescheduling operation.
64 SchedulerType::EnableScheduling(kernel, cores_needing_scheduling); 61 SchedulerType::EnableScheduling(kernel, cores_needing_scheduling);
@@ -67,7 +64,7 @@ public:
67 64
68private: 65private:
69 KernelCore& kernel; 66 KernelCore& kernel;
70 Common::SpinLock spin_lock{}; 67 KAlignedSpinLock spin_lock{};
71 s32 lock_count{}; 68 s32 lock_count{};
72 KThread* owner_thread{}; 69 KThread* owner_thread{};
73}; 70};
diff --git a/src/core/hle/kernel/k_scoped_lock.h b/src/core/hle/kernel/k_scoped_lock.h
index d7cc557b2..72c3b0252 100644
--- a/src/core/hle/kernel/k_scoped_lock.h
+++ b/src/core/hle/kernel/k_scoped_lock.h
@@ -20,19 +20,22 @@ concept KLockable = !std::is_reference_v<T> && requires(T & t) {
20}; 20};
21 21
22template <typename T> 22template <typename T>
23requires KLockable<T> class KScopedLock { 23requires KLockable<T> class [[nodiscard]] KScopedLock {
24public: 24public:
25 explicit KScopedLock(T* l) : lock_ptr(l) { 25 explicit KScopedLock(T * l) : lock_ptr(l) {
26 this->lock_ptr->Lock(); 26 this->lock_ptr->Lock();
27 } 27 }
28 explicit KScopedLock(T& l) : KScopedLock(std::addressof(l)) { /* ... */ 28 explicit KScopedLock(T & l) : KScopedLock(std::addressof(l)) {}
29 } 29
30 ~KScopedLock() { 30 ~KScopedLock() {
31 this->lock_ptr->Unlock(); 31 this->lock_ptr->Unlock();
32 } 32 }
33 33
34 KScopedLock(const KScopedLock&) = delete; 34 KScopedLock(const KScopedLock&) = delete;
35 KScopedLock(KScopedLock&&) = delete; 35 KScopedLock& operator=(const KScopedLock&) = delete;
36
37 KScopedLock(KScopedLock &&) = delete;
38 KScopedLock& operator=(KScopedLock&&) = delete;
36 39
37private: 40private:
38 T* lock_ptr; 41 T* lock_ptr;
diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
index f8189e107..ebecf0c77 100644
--- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
+++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h
@@ -15,9 +15,9 @@
15 15
16namespace Kernel { 16namespace Kernel {
17 17
18class KScopedSchedulerLockAndSleep { 18class [[nodiscard]] KScopedSchedulerLockAndSleep {
19public: 19public:
20 explicit KScopedSchedulerLockAndSleep(KernelCore& kernel, KThread* t, s64 timeout) 20 explicit KScopedSchedulerLockAndSleep(KernelCore & kernel, KThread * t, s64 timeout)
21 : kernel(kernel), thread(t), timeout_tick(timeout) { 21 : kernel(kernel), thread(t), timeout_tick(timeout) {
22 // Lock the scheduler. 22 // Lock the scheduler.
23 kernel.GlobalSchedulerContext().scheduler_lock.Lock(); 23 kernel.GlobalSchedulerContext().scheduler_lock.Lock();
diff --git a/src/core/hle/kernel/k_spin_lock.h b/src/core/hle/kernel/k_spin_lock.h
index 12c4b2e88..4d87d006a 100644
--- a/src/core/hle/kernel/k_spin_lock.h
+++ b/src/core/hle/kernel/k_spin_lock.h
@@ -28,6 +28,12 @@ private:
28 std::atomic_flag lck = ATOMIC_FLAG_INIT; 28 std::atomic_flag lck = ATOMIC_FLAG_INIT;
29}; 29};
30 30
31// TODO(bunnei): Alias for now, in case we want to implement these accurately in the future.
32using KAlignedSpinLock = KSpinLock;
33using KNotAlignedSpinLock = KSpinLock;
34
31using KScopedSpinLock = KScopedLock<KSpinLock>; 35using KScopedSpinLock = KScopedLock<KSpinLock>;
36using KScopedAlignedSpinLock = KScopedLock<KAlignedSpinLock>;
37using KScopedNotAlignedSpinLock = KScopedLock<KNotAlignedSpinLock>;
32 38
33} // namespace Kernel 39} // namespace Kernel
diff --git a/src/core/hle/kernel/k_system_control.cpp b/src/core/hle/kernel/k_system_control.cpp
deleted file mode 100644
index aa1682f69..000000000
--- a/src/core/hle/kernel/k_system_control.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
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 <random>
6
7#include "core/hle/kernel/k_system_control.h"
8
9namespace Kernel {
10
11namespace {
12template <typename F>
13u64 GenerateUniformRange(u64 min, u64 max, F f) {
14 // Handle the case where the difference is too large to represent.
15 if (max == std::numeric_limits<u64>::max() && min == std::numeric_limits<u64>::min()) {
16 return f();
17 }
18
19 // Iterate until we get a value in range.
20 const u64 range_size = ((max + 1) - min);
21 const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
22 while (true) {
23 if (const u64 rnd = f(); rnd < effective_max) {
24 return min + (rnd % range_size);
25 }
26 }
27}
28
29} // Anonymous namespace
30
31u64 KSystemControl::GenerateRandomU64() {
32 static std::random_device device;
33 static std::mt19937 gen(device());
34 static std::uniform_int_distribution<u64> distribution(1, std::numeric_limits<u64>::max());
35 return distribution(gen);
36}
37
38u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) {
39 return GenerateUniformRange(min, max, GenerateRandomU64);
40}
41
42} // namespace Kernel
diff --git a/src/core/hle/kernel/k_system_control.h b/src/core/hle/kernel/k_system_control.h
index 1d5b64ffa..d755082c2 100644
--- a/src/core/hle/kernel/k_system_control.h
+++ b/src/core/hle/kernel/k_system_control.h
@@ -6,14 +6,18 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9namespace Kernel { 9#define BOARD_NINTENDO_NX
10
11#ifdef BOARD_NINTENDO_NX
10 12
11class KSystemControl { 13#include "core/hle/kernel/board/nintendo/nx/k_system_control.h"
12public:
13 KSystemControl() = default;
14 14
15 static u64 GenerateRandomRange(u64 min, u64 max); 15namespace Kernel {
16 static u64 GenerateRandomU64(); 16
17}; 17using Kernel::Board::Nintendo::Nx::KSystemControl;
18 18
19} // namespace Kernel 19} // namespace Kernel
20
21#else
22#error "Unknown board for KSystemControl"
23#endif
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 1c19b23dc..1c86fdd20 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -14,10 +14,10 @@
14 14
15#include "common/common_types.h" 15#include "common/common_types.h"
16#include "common/intrusive_red_black_tree.h" 16#include "common/intrusive_red_black_tree.h"
17#include "common/spin_lock.h"
18#include "core/arm/arm_interface.h" 17#include "core/arm/arm_interface.h"
19#include "core/hle/kernel/k_affinity_mask.h" 18#include "core/hle/kernel/k_affinity_mask.h"
20#include "core/hle/kernel/k_light_lock.h" 19#include "core/hle/kernel/k_light_lock.h"
20#include "core/hle/kernel/k_spin_lock.h"
21#include "core/hle/kernel/k_synchronization_object.h" 21#include "core/hle/kernel/k_synchronization_object.h"
22#include "core/hle/kernel/object.h" 22#include "core/hle/kernel/object.h"
23#include "core/hle/kernel/svc_common.h" 23#include "core/hle/kernel/svc_common.h"
@@ -732,7 +732,7 @@ private:
732 s8 priority_inheritance_count{}; 732 s8 priority_inheritance_count{};
733 bool resource_limit_release_hint{}; 733 bool resource_limit_release_hint{};
734 StackParameters stack_parameters{}; 734 StackParameters stack_parameters{};
735 Common::SpinLock context_guard{}; 735 KSpinLock context_guard{};
736 736
737 // For emulation 737 // For emulation
738 std::shared_ptr<Common::Fiber> host_context{}; 738 std::shared_ptr<Common::Fiber> host_context{};
diff --git a/src/core/hle/kernel/k_trace.h b/src/core/hle/kernel/k_trace.h
new file mode 100644
index 000000000..91ebf9ab2
--- /dev/null
+++ b/src/core/hle/kernel/k_trace.h
@@ -0,0 +1,12 @@
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
7namespace Kernel {
8
9constexpr bool IsKTraceEnabled = false;
10constexpr std::size_t KTraceBufferSize = IsKTraceEnabled ? 16 * 1024 * 1024 : 0;
11
12} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 5b6c7792e..8fd990577 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -1,4 +1,4 @@
1// Copyright 2014 Citra 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
@@ -12,6 +12,7 @@
12#include <utility> 12#include <utility>
13 13
14#include "common/assert.h" 14#include "common/assert.h"
15#include "common/common_sizes.h"
15#include "common/logging/log.h" 16#include "common/logging/log.h"
16#include "common/microprofile.h" 17#include "common/microprofile.h"
17#include "common/thread.h" 18#include "common/thread.h"
@@ -143,10 +144,10 @@ struct KernelCore::Impl {
143 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000) 144 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000)
144 .IsSuccess()); 145 .IsSuccess());
145 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); 146 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
146 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess()); 147 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess());
147 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) 148 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
148 .IsSuccess()); 149 .IsSuccess());
149 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 933).IsSuccess()); 150 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess());
150 151
151 // Derived from recent software updates. The kernel reserves 27MB 152 // Derived from recent software updates. The kernel reserves 27MB
152 constexpr u64 kernel_size{0x1b00000}; 153 constexpr u64 kernel_size{0x1b00000};
@@ -268,45 +269,314 @@ struct KernelCore::Impl {
268 return schedulers[thread_id]->GetCurrentThread(); 269 return schedulers[thread_id]->GetCurrentThread();
269 } 270 }
270 271
272 void DeriveInitialMemoryLayout(KMemoryLayout& memory_layout) {
273 // Insert the root region for the virtual memory tree, from which all other regions will
274 // derive.
275 memory_layout.GetVirtualMemoryRegionTree().InsertDirectly(
276 KernelVirtualAddressSpaceBase,
277 KernelVirtualAddressSpaceBase + KernelVirtualAddressSpaceSize - 1);
278
279 // Insert the root region for the physical memory tree, from which all other regions will
280 // derive.
281 memory_layout.GetPhysicalMemoryRegionTree().InsertDirectly(
282 KernelPhysicalAddressSpaceBase,
283 KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceSize - 1);
284
285 // Save start and end for ease of use.
286 const VAddr code_start_virt_addr = KernelVirtualAddressCodeBase;
287 const VAddr code_end_virt_addr = KernelVirtualAddressCodeEnd;
288
289 // Setup the containing kernel region.
290 constexpr size_t KernelRegionSize = Common::Size_1_GB;
291 constexpr size_t KernelRegionAlign = Common::Size_1_GB;
292 constexpr VAddr kernel_region_start =
293 Common::AlignDown(code_start_virt_addr, KernelRegionAlign);
294 size_t kernel_region_size = KernelRegionSize;
295 if (!(kernel_region_start + KernelRegionSize - 1 <= KernelVirtualAddressSpaceLast)) {
296 kernel_region_size = KernelVirtualAddressSpaceEnd - kernel_region_start;
297 }
298 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
299 kernel_region_start, kernel_region_size, KMemoryRegionType_Kernel));
300
301 // Setup the code region.
302 constexpr size_t CodeRegionAlign = PageSize;
303 constexpr VAddr code_region_start =
304 Common::AlignDown(code_start_virt_addr, CodeRegionAlign);
305 constexpr VAddr code_region_end = Common::AlignUp(code_end_virt_addr, CodeRegionAlign);
306 constexpr size_t code_region_size = code_region_end - code_region_start;
307 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
308 code_region_start, code_region_size, KMemoryRegionType_KernelCode));
309
310 // Setup board-specific device physical regions.
311 Init::SetupDevicePhysicalMemoryRegions(memory_layout);
312
313 // Determine the amount of space needed for the misc region.
314 size_t misc_region_needed_size;
315 {
316 // Each core has a one page stack for all three stack types (Main, Idle, Exception).
317 misc_region_needed_size = Core::Hardware::NUM_CPU_CORES * (3 * (PageSize + PageSize));
318
319 // Account for each auto-map device.
320 for (const auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
321 if (region.HasTypeAttribute(KMemoryRegionAttr_ShouldKernelMap)) {
322 // Check that the region is valid.
323 ASSERT(region.GetEndAddress() != 0);
324
325 // Account for the region.
326 misc_region_needed_size +=
327 PageSize + (Common::AlignUp(region.GetLastAddress(), PageSize) -
328 Common::AlignDown(region.GetAddress(), PageSize));
329 }
330 }
331
332 // Multiply the needed size by three, to account for the need for guard space.
333 misc_region_needed_size *= 3;
334 }
335
336 // Decide on the actual size for the misc region.
337 constexpr size_t MiscRegionAlign = KernelAslrAlignment;
338 constexpr size_t MiscRegionMinimumSize = Common::Size_32_MB;
339 const size_t misc_region_size = Common::AlignUp(
340 std::max(misc_region_needed_size, MiscRegionMinimumSize), MiscRegionAlign);
341 ASSERT(misc_region_size > 0);
342
343 // Setup the misc region.
344 const VAddr misc_region_start =
345 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
346 misc_region_size, MiscRegionAlign, KMemoryRegionType_Kernel);
347 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
348 misc_region_start, misc_region_size, KMemoryRegionType_KernelMisc));
349
350 // Setup the stack region.
351 constexpr size_t StackRegionSize = Common::Size_14_MB;
352 constexpr size_t StackRegionAlign = KernelAslrAlignment;
353 const VAddr stack_region_start =
354 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
355 StackRegionSize, StackRegionAlign, KMemoryRegionType_Kernel);
356 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
357 stack_region_start, StackRegionSize, KMemoryRegionType_KernelStack));
358
359 // Determine the size of the resource region.
360 const size_t resource_region_size = memory_layout.GetResourceRegionSizeForInit();
361
362 // Determine the size of the slab region.
363 const size_t slab_region_size = Common::AlignUp(KernelSlabHeapSize, PageSize);
364 ASSERT(slab_region_size <= resource_region_size);
365
366 // Setup the slab region.
367 const PAddr code_start_phys_addr = KernelPhysicalAddressCodeBase;
368 const PAddr code_end_phys_addr = code_start_phys_addr + code_region_size;
369 const PAddr slab_start_phys_addr = code_end_phys_addr;
370 const PAddr slab_end_phys_addr = slab_start_phys_addr + slab_region_size;
371 constexpr size_t SlabRegionAlign = KernelAslrAlignment;
372 const size_t slab_region_needed_size =
373 Common::AlignUp(code_end_phys_addr + slab_region_size, SlabRegionAlign) -
374 Common::AlignDown(code_end_phys_addr, SlabRegionAlign);
375 const VAddr slab_region_start =
376 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
377 slab_region_needed_size, SlabRegionAlign, KMemoryRegionType_Kernel) +
378 (code_end_phys_addr % SlabRegionAlign);
379 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
380 slab_region_start, slab_region_size, KMemoryRegionType_KernelSlab));
381
382 // Setup the temp region.
383 constexpr size_t TempRegionSize = Common::Size_128_MB;
384 constexpr size_t TempRegionAlign = KernelAslrAlignment;
385 const VAddr temp_region_start =
386 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
387 TempRegionSize, TempRegionAlign, KMemoryRegionType_Kernel);
388 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(temp_region_start, TempRegionSize,
389 KMemoryRegionType_KernelTemp));
390
391 // Automatically map in devices that have auto-map attributes.
392 for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
393 // We only care about kernel regions.
394 if (!region.IsDerivedFrom(KMemoryRegionType_Kernel)) {
395 continue;
396 }
397
398 // Check whether we should map the region.
399 if (!region.HasTypeAttribute(KMemoryRegionAttr_ShouldKernelMap)) {
400 continue;
401 }
402
403 // If this region has already been mapped, no need to consider it.
404 if (region.HasTypeAttribute(KMemoryRegionAttr_DidKernelMap)) {
405 continue;
406 }
407
408 // Check that the region is valid.
409 ASSERT(region.GetEndAddress() != 0);
410
411 // Set the attribute to note we've mapped this region.
412 region.SetTypeAttribute(KMemoryRegionAttr_DidKernelMap);
413
414 // Create a virtual pair region and insert it into the tree.
415 const PAddr map_phys_addr = Common::AlignDown(region.GetAddress(), PageSize);
416 const size_t map_size =
417 Common::AlignUp(region.GetEndAddress(), PageSize) - map_phys_addr;
418 const VAddr map_virt_addr =
419 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(
420 map_size, PageSize, KMemoryRegionType_KernelMisc, PageSize);
421 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
422 map_virt_addr, map_size, KMemoryRegionType_KernelMiscMappedDevice));
423 region.SetPairAddress(map_virt_addr + region.GetAddress() - map_phys_addr);
424 }
425
426 Init::SetupDramPhysicalMemoryRegions(memory_layout);
427
428 // Insert a physical region for the kernel code region.
429 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
430 code_start_phys_addr, code_region_size, KMemoryRegionType_DramKernelCode));
431
432 // Insert a physical region for the kernel slab region.
433 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
434 slab_start_phys_addr, slab_region_size, KMemoryRegionType_DramKernelSlab));
435
436 // Determine size available for kernel page table heaps, requiring > 8 MB.
437 const PAddr resource_end_phys_addr = slab_start_phys_addr + resource_region_size;
438 const size_t page_table_heap_size = resource_end_phys_addr - slab_end_phys_addr;
439 ASSERT(page_table_heap_size / Common::Size_4_MB > 2);
440
441 // Insert a physical region for the kernel page table heap region
442 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
443 slab_end_phys_addr, page_table_heap_size, KMemoryRegionType_DramKernelPtHeap));
444
445 // All DRAM regions that we haven't tagged by this point will be mapped under the linear
446 // mapping. Tag them.
447 for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
448 if (region.GetType() == KMemoryRegionType_Dram) {
449 // Check that the region is valid.
450 ASSERT(region.GetEndAddress() != 0);
451
452 // Set the linear map attribute.
453 region.SetTypeAttribute(KMemoryRegionAttr_LinearMapped);
454 }
455 }
456
457 // Get the linear region extents.
458 const auto linear_extents =
459 memory_layout.GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(
460 KMemoryRegionAttr_LinearMapped);
461 ASSERT(linear_extents.GetEndAddress() != 0);
462
463 // Setup the linear mapping region.
464 constexpr size_t LinearRegionAlign = Common::Size_1_GB;
465 const PAddr aligned_linear_phys_start =
466 Common::AlignDown(linear_extents.GetAddress(), LinearRegionAlign);
467 const size_t linear_region_size =
468 Common::AlignUp(linear_extents.GetEndAddress(), LinearRegionAlign) -
469 aligned_linear_phys_start;
470 const VAddr linear_region_start =
471 memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(
472 linear_region_size, LinearRegionAlign, KMemoryRegionType_None, LinearRegionAlign);
473
474 const u64 linear_region_phys_to_virt_diff = linear_region_start - aligned_linear_phys_start;
475
476 // Map and create regions for all the linearly-mapped data.
477 {
478 PAddr cur_phys_addr = 0;
479 u64 cur_size = 0;
480 for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
481 if (!region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) {
482 continue;
483 }
484
485 ASSERT(region.GetEndAddress() != 0);
486
487 if (cur_size == 0) {
488 cur_phys_addr = region.GetAddress();
489 cur_size = region.GetSize();
490 } else if (cur_phys_addr + cur_size == region.GetAddress()) {
491 cur_size += region.GetSize();
492 } else {
493 cur_phys_addr = region.GetAddress();
494 cur_size = region.GetSize();
495 }
496
497 const VAddr region_virt_addr =
498 region.GetAddress() + linear_region_phys_to_virt_diff;
499 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
500 region_virt_addr, region.GetSize(),
501 GetTypeForVirtualLinearMapping(region.GetType())));
502 region.SetPairAddress(region_virt_addr);
503
504 KMemoryRegion* virt_region =
505 memory_layout.GetVirtualMemoryRegionTree().FindModifiable(region_virt_addr);
506 ASSERT(virt_region != nullptr);
507 virt_region->SetPairAddress(region.GetAddress());
508 }
509 }
510
511 // Insert regions for the initial page table region.
512 ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
513 resource_end_phys_addr, KernelPageTableHeapSize, KMemoryRegionType_DramKernelInitPt));
514 ASSERT(memory_layout.GetVirtualMemoryRegionTree().Insert(
515 resource_end_phys_addr + linear_region_phys_to_virt_diff, KernelPageTableHeapSize,
516 KMemoryRegionType_VirtualDramKernelInitPt));
517
518 // All linear-mapped DRAM regions that we haven't tagged by this point will be allocated to
519 // some pool partition. Tag them.
520 for (auto& region : memory_layout.GetPhysicalMemoryRegionTree()) {
521 if (region.GetType() == (KMemoryRegionType_Dram | KMemoryRegionAttr_LinearMapped)) {
522 region.SetType(KMemoryRegionType_DramPoolPartition);
523 }
524 }
525
526 // Setup all other memory regions needed to arrange the pool partitions.
527 Init::SetupPoolPartitionMemoryRegions(memory_layout);
528
529 // Cache all linear regions in their own trees for faster access, later.
530 memory_layout.InitializeLinearMemoryRegionTrees(aligned_linear_phys_start,
531 linear_region_start);
532 }
533
271 void InitializeMemoryLayout() { 534 void InitializeMemoryLayout() {
272 // Initialize memory layout 535 // Derive the initial memory layout from the emulated board
273 constexpr KMemoryLayout layout{KMemoryLayout::GetDefaultLayout()}; 536 KMemoryLayout memory_layout;
537 DeriveInitialMemoryLayout(memory_layout);
538
539 const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents();
540 const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents();
541 const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
542
543 // Initialize memory managers
544 memory_manager = std::make_unique<KMemoryManager>();
545 memory_manager->InitializeManager(KMemoryManager::Pool::Application,
546 application_pool.GetAddress(),
547 application_pool.GetEndAddress());
548 memory_manager->InitializeManager(KMemoryManager::Pool::Applet, applet_pool.GetAddress(),
549 applet_pool.GetEndAddress());
550 memory_manager->InitializeManager(KMemoryManager::Pool::System, system_pool.GetAddress(),
551 system_pool.GetEndAddress());
552
553 // Setup memory regions for emulated processes
554 // TODO(bunnei): These should not be hardcoded regions initialized within the kernel
274 constexpr std::size_t hid_size{0x40000}; 555 constexpr std::size_t hid_size{0x40000};
275 constexpr std::size_t font_size{0x1100000}; 556 constexpr std::size_t font_size{0x1100000};
276 constexpr std::size_t irs_size{0x8000}; 557 constexpr std::size_t irs_size{0x8000};
277 constexpr std::size_t time_size{0x1000}; 558 constexpr std::size_t time_size{0x1000};
278 constexpr PAddr hid_addr{layout.System().StartAddress()};
279 constexpr PAddr font_pa{layout.System().StartAddress() + hid_size};
280 constexpr PAddr irs_addr{layout.System().StartAddress() + hid_size + font_size};
281 constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size};
282 559
283 // Initialize memory manager 560 const PAddr hid_phys_addr{system_pool.GetAddress()};
284 memory_manager = std::make_unique<KMemoryManager>(); 561 const PAddr font_phys_addr{system_pool.GetAddress() + hid_size};
285 memory_manager->InitializeManager(KMemoryManager::Pool::Application, 562 const PAddr irs_phys_addr{system_pool.GetAddress() + hid_size + font_size};
286 layout.Application().StartAddress(), 563 const PAddr time_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size};
287 layout.Application().EndAddress());
288 memory_manager->InitializeManager(KMemoryManager::Pool::Applet,
289 layout.Applet().StartAddress(),
290 layout.Applet().EndAddress());
291 memory_manager->InitializeManager(KMemoryManager::Pool::System,
292 layout.System().StartAddress(),
293 layout.System().EndAddress());
294 564
295 hid_shared_mem = Kernel::KSharedMemory::Create( 565 hid_shared_mem = Kernel::KSharedMemory::Create(
296 system.Kernel(), system.DeviceMemory(), nullptr, {hid_addr, hid_size / PageSize}, 566 system.Kernel(), system.DeviceMemory(), nullptr, {hid_phys_addr, hid_size / PageSize},
297 KMemoryPermission::None, KMemoryPermission::Read, hid_addr, hid_size, 567 KMemoryPermission::None, KMemoryPermission::Read, hid_phys_addr, hid_size,
298 "HID:SharedMemory"); 568 "HID:SharedMemory");
299 font_shared_mem = Kernel::KSharedMemory::Create( 569 font_shared_mem = Kernel::KSharedMemory::Create(
300 system.Kernel(), system.DeviceMemory(), nullptr, {font_pa, font_size / PageSize}, 570 system.Kernel(), system.DeviceMemory(), nullptr, {font_phys_addr, font_size / PageSize},
301 KMemoryPermission::None, KMemoryPermission::Read, font_pa, font_size, 571 KMemoryPermission::None, KMemoryPermission::Read, font_phys_addr, font_size,
302 "Font:SharedMemory"); 572 "Font:SharedMemory");
303 irs_shared_mem = Kernel::KSharedMemory::Create( 573 irs_shared_mem = Kernel::KSharedMemory::Create(
304 system.Kernel(), system.DeviceMemory(), nullptr, {irs_addr, irs_size / PageSize}, 574 system.Kernel(), system.DeviceMemory(), nullptr, {irs_phys_addr, irs_size / PageSize},
305 KMemoryPermission::None, KMemoryPermission::Read, irs_addr, irs_size, 575 KMemoryPermission::None, KMemoryPermission::Read, irs_phys_addr, irs_size,
306 "IRS:SharedMemory"); 576 "IRS:SharedMemory");
307 time_shared_mem = Kernel::KSharedMemory::Create( 577 time_shared_mem = Kernel::KSharedMemory::Create(
308 system.Kernel(), system.DeviceMemory(), nullptr, {time_addr, time_size / PageSize}, 578 system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize},
309 KMemoryPermission::None, KMemoryPermission::Read, time_addr, time_size, 579 KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size,
310 "Time:SharedMemory"); 580 "Time:SharedMemory");
311 581
312 // Allocate slab heaps 582 // Allocate slab heaps
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 56906f2da..a500e63bc 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -1,4 +1,4 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP 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
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index d91237cba..4374487a3 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -231,6 +231,7 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
231 {10, nullptr, "PerformSystemButtonPressing"}, 231 {10, nullptr, "PerformSystemButtonPressing"},
232 {20, nullptr, "InvalidateTransitionLayer"}, 232 {20, nullptr, "InvalidateTransitionLayer"},
233 {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, 233 {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
234 {31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
234 {40, nullptr, "GetAppletResourceUsageInfo"}, 235 {40, nullptr, "GetAppletResourceUsageInfo"},
235 {100, nullptr, "SetCpuBoostModeForApplet"}, 236 {100, nullptr, "SetCpuBoostModeForApplet"},
236 {101, nullptr, "CancelCpuBoostModeForApplet"}, 237 {101, nullptr, "CancelCpuBoostModeForApplet"},
@@ -242,6 +243,7 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
242 {130, nullptr, "FriendInvitationSetApplicationParameter"}, 243 {130, nullptr, "FriendInvitationSetApplicationParameter"},
243 {131, nullptr, "FriendInvitationClearApplicationParameter"}, 244 {131, nullptr, "FriendInvitationClearApplicationParameter"},
244 {132, nullptr, "FriendInvitationPushApplicationParameter"}, 245 {132, nullptr, "FriendInvitationPushApplicationParameter"},
246 {900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
245 }; 247 };
246 // clang-format on 248 // clang-format on
247 249
@@ -297,6 +299,7 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
297 {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, 299 {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"},
298 {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, 300 {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
299 {110, nullptr, "SetApplicationAlbumUserData"}, 301 {110, nullptr, "SetApplicationAlbumUserData"},
302 {120, nullptr, "SaveCurrentScreenshot"},
300 {1000, nullptr, "GetDebugStorageChannel"}, 303 {1000, nullptr, "GetDebugStorageChannel"},
301 }; 304 };
302 // clang-format on 305 // clang-format on
@@ -645,6 +648,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
645 {11, nullptr, "ReleaseSleepLock"}, 648 {11, nullptr, "ReleaseSleepLock"},
646 {12, nullptr, "ReleaseSleepLockTransiently"}, 649 {12, nullptr, "ReleaseSleepLockTransiently"},
647 {13, nullptr, "GetAcquiredSleepLockEvent"}, 650 {13, nullptr, "GetAcquiredSleepLockEvent"},
651 {14, nullptr, "GetWakeupCount"},
648 {20, nullptr, "PushToGeneralChannel"}, 652 {20, nullptr, "PushToGeneralChannel"},
649 {30, nullptr, "GetHomeButtonReaderLockAccessor"}, 653 {30, nullptr, "GetHomeButtonReaderLockAccessor"},
650 {31, nullptr, "GetReaderLockAccessorEx"}, 654 {31, nullptr, "GetReaderLockAccessorEx"},
@@ -656,6 +660,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
656 {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"}, 660 {53, &ICommonStateGetter::BeginVrModeEx, "BeginVrModeEx"},
657 {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"}, 661 {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
658 {55, nullptr, "IsInControllerFirmwareUpdateSection"}, 662 {55, nullptr, "IsInControllerFirmwareUpdateSection"},
663 {59, nullptr, "SetVrPositionForDebug"},
659 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, 664 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
660 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, 665 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
661 {62, nullptr, "GetHdcpAuthenticationState"}, 666 {62, nullptr, "GetHdcpAuthenticationState"},
@@ -664,14 +669,21 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
664 {65, nullptr, "GetApplicationIdByContentActionName"}, 669 {65, nullptr, "GetApplicationIdByContentActionName"},
665 {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, 670 {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
666 {67, nullptr, "CancelCpuBoostMode"}, 671 {67, nullptr, "CancelCpuBoostMode"},
672 {68, nullptr, "GetBuiltInDisplayType"},
667 {80, nullptr, "PerformSystemButtonPressingIfInFocus"}, 673 {80, nullptr, "PerformSystemButtonPressingIfInFocus"},
668 {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, 674 {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
669 {91, nullptr, "GetCurrentPerformanceConfiguration"}, 675 {91, nullptr, "GetCurrentPerformanceConfiguration"},
670 {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, 676 {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
677 {110, nullptr, "OpenMyGpuErrorHandler"},
671 {200, nullptr, "GetOperationModeSystemInfo"}, 678 {200, nullptr, "GetOperationModeSystemInfo"},
672 {300, nullptr, "GetSettingsPlatformRegion"}, 679 {300, nullptr, "GetSettingsPlatformRegion"},
673 {400, nullptr, "ActivateMigrationService"}, 680 {400, nullptr, "ActivateMigrationService"},
674 {401, nullptr, "DeactivateMigrationService"}, 681 {401, nullptr, "DeactivateMigrationService"},
682 {500, nullptr, "DisableSleepTillShutdown"},
683 {501, nullptr, "SuppressDisablingSleepTemporarily"},
684 {502, nullptr, "IsSleepEnabled"},
685 {503, nullptr, "IsDisablingSleepSuppressed"},
686 {900, nullptr, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
675 }; 687 };
676 // clang-format on 688 // clang-format on
677 689
@@ -1203,11 +1215,14 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1203 {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, 1215 {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
1204 {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, 1216 {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
1205 {27, nullptr, "CreateCacheStorage"}, 1217 {27, nullptr, "CreateCacheStorage"},
1218 {28, nullptr, "GetSaveDataSizeMax"},
1219 {29, nullptr, "GetCacheStorageMax"},
1206 {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, 1220 {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
1207 {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, 1221 {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
1208 {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, 1222 {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
1209 {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"}, 1223 {33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
1210 {34, nullptr, "SelectApplicationLicense"}, 1224 {34, nullptr, "SelectApplicationLicense"},
1225 {35, nullptr, "GetDeviceSaveDataSizeMax"},
1211 {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, 1226 {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
1212 {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"}, 1227 {50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
1213 {60, nullptr, "SetMediaPlaybackStateForApplication"}, 1228 {60, nullptr, "SetMediaPlaybackStateForApplication"},
@@ -1231,6 +1246,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1231 {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"}, 1246 {123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
1232 {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, 1247 {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
1233 {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, 1248 {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
1249 {131, nullptr, "SetDelayTimeToAbortOnGpuError"},
1234 {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, 1250 {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
1235 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, 1251 {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"},
1236 {150, nullptr, "GetNotificationStorageChannelEvent"}, 1252 {150, nullptr, "GetNotificationStorageChannelEvent"},
@@ -1239,6 +1255,8 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1239 {170, nullptr, "SetHdcpAuthenticationActivated"}, 1255 {170, nullptr, "SetHdcpAuthenticationActivated"},
1240 {180, nullptr, "GetLaunchRequiredVersion"}, 1256 {180, nullptr, "GetLaunchRequiredVersion"},
1241 {181, nullptr, "UpgradeLaunchRequiredVersion"}, 1257 {181, nullptr, "UpgradeLaunchRequiredVersion"},
1258 {190, nullptr, "SendServerMaintenanceOverlayNotification"},
1259 {200, nullptr, "GetLastApplicationExitReason"},
1242 {500, nullptr, "StartContinuousRecordingFlushForDebug"}, 1260 {500, nullptr, "StartContinuousRecordingFlushForDebug"},
1243 {1000, nullptr, "CreateMovieMaker"}, 1261 {1000, nullptr, "CreateMovieMaker"},
1244 {1001, nullptr, "PrepareForJit"}, 1262 {1001, nullptr, "PrepareForJit"},
@@ -1705,9 +1723,12 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
1705 {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, 1723 {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"},
1706 {30, nullptr, "GetHomeButtonWriterLockAccessor"}, 1724 {30, nullptr, "GetHomeButtonWriterLockAccessor"},
1707 {31, nullptr, "GetWriterLockAccessorEx"}, 1725 {31, nullptr, "GetWriterLockAccessorEx"},
1726 {40, nullptr, "IsSleepEnabled"},
1727 {41, nullptr, "IsRebootEnabled"},
1708 {100, nullptr, "PopRequestLaunchApplicationForDebug"}, 1728 {100, nullptr, "PopRequestLaunchApplicationForDebug"},
1709 {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"}, 1729 {110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
1710 {200, nullptr, "LaunchDevMenu"}, 1730 {200, nullptr, "LaunchDevMenu"},
1731 {1000, nullptr, "SetLastApplicationExitReason"},
1711 }; 1732 };
1712 // clang-format on 1733 // clang-format on
1713 1734
@@ -1751,6 +1772,7 @@ IGlobalStateController::IGlobalStateController(Core::System& system_)
1751 {13, nullptr, "UpdateDefaultDisplayResolution"}, 1772 {13, nullptr, "UpdateDefaultDisplayResolution"},
1752 {14, nullptr, "ShouldSleepOnBoot"}, 1773 {14, nullptr, "ShouldSleepOnBoot"},
1753 {15, nullptr, "GetHdcpAuthenticationFailedEvent"}, 1774 {15, nullptr, "GetHdcpAuthenticationFailedEvent"},
1775 {30, nullptr, "OpenCradleFirmwareUpdater"},
1754 }; 1776 };
1755 // clang-format on 1777 // clang-format on
1756 1778
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 8d657c0bf..0f51e5871 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -118,8 +118,10 @@ AOC_U::AOC_U(Core::System& system_)
118 {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, 118 {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"},
119 {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, 119 {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"},
120 {9, nullptr, "GetAddOnContentLostErrorCode"}, 120 {9, nullptr, "GetAddOnContentLostErrorCode"},
121 {10, nullptr, "GetAddOnContentListChangedEventWithProcessId"},
121 {100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"}, 122 {100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"},
122 {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"}, 123 {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"},
124 {110, nullptr, "CreateContentsServiceManager"},
123 }; 125 };
124 // clang-format on 126 // clang-format on
125 127
diff --git a/src/core/hle/service/audio/audin_a.cpp b/src/core/hle/service/audio/audin_a.cpp
index 79c3aa920..10acaad19 100644
--- a/src/core/hle/service/audio/audin_a.cpp
+++ b/src/core/hle/service/audio/audin_a.cpp
@@ -9,10 +9,10 @@ namespace Service::Audio {
9AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} { 9AudInA::AudInA(Core::System& system_) : ServiceFramework{system_, "audin:a"} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "RequestSuspendAudioIns"}, 12 {0, nullptr, "RequestSuspend"},
13 {1, nullptr, "RequestResumeAudioIns"}, 13 {1, nullptr, "RequestResume"},
14 {2, nullptr, "GetAudioInsProcessMasterVolume"}, 14 {2, nullptr, "GetProcessMasterVolume"},
15 {3, nullptr, "SetAudioInsProcessMasterVolume"}, 15 {3, nullptr, "SetProcessMasterVolume"},
16 }; 16 };
17 // clang-format on 17 // clang-format on
18 18
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 26a6deddf..ecd05e4a6 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -15,19 +15,19 @@ public:
15 // clang-format off 15 // clang-format off
16 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
17 {0, nullptr, "GetAudioInState"}, 17 {0, nullptr, "GetAudioInState"},
18 {1, nullptr, "StartAudioIn"}, 18 {1, nullptr, "Start"},
19 {2, nullptr, "StopAudioIn"}, 19 {2, nullptr, "Stop"},
20 {3, nullptr, "AppendAudioInBuffer"}, 20 {3, nullptr, "AppendAudioInBuffer"},
21 {4, nullptr, "RegisterBufferEvent"}, 21 {4, nullptr, "RegisterBufferEvent"},
22 {5, nullptr, "GetReleasedAudioInBuffer"}, 22 {5, nullptr, "GetReleasedAudioInBuffer"},
23 {6, nullptr, "ContainsAudioInBuffer"}, 23 {6, nullptr, "ContainsAudioInBuffer"},
24 {7, nullptr, "AppendAudioInBufferWithUserEvent"}, 24 {7, nullptr, "AppendUacInBuffer"},
25 {8, nullptr, "AppendAudioInBufferAuto"}, 25 {8, nullptr, "AppendAudioInBufferAuto"},
26 {9, nullptr, "GetReleasedAudioInBufferAuto"}, 26 {9, nullptr, "GetReleasedAudioInBuffersAuto"},
27 {10, nullptr, "AppendAudioInBufferWithUserEventAuto"}, 27 {10, nullptr, "AppendUacInBufferAuto"},
28 {11, nullptr, "GetAudioInBufferCount"}, 28 {11, nullptr, "GetAudioInBufferCount"},
29 {12, nullptr, "SetAudioInDeviceGain"}, 29 {12, nullptr, "SetDeviceGain"},
30 {13, nullptr, "GetAudioInDeviceGain"}, 30 {13, nullptr, "GetDeviceGain"},
31 {14, nullptr, "FlushAudioInBuffers"}, 31 {14, nullptr, "FlushAudioInBuffers"},
32 }; 32 };
33 // clang-format on 33 // clang-format on
diff --git a/src/core/hle/service/audio/audout_a.cpp b/src/core/hle/service/audio/audout_a.cpp
index 19825fd5d..3ee522b50 100644
--- a/src/core/hle/service/audio/audout_a.cpp
+++ b/src/core/hle/service/audio/audout_a.cpp
@@ -9,12 +9,12 @@ namespace Service::Audio {
9AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} { 9AudOutA::AudOutA(Core::System& system_) : ServiceFramework{system_, "audout:a"} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "RequestSuspendAudioOuts"}, 12 {0, nullptr, "RequestSuspend"},
13 {1, nullptr, "RequestResumeAudioOuts"}, 13 {1, nullptr, "RequestResume"},
14 {2, nullptr, "GetAudioOutsProcessMasterVolume"}, 14 {2, nullptr, "GetProcessMasterVolume"},
15 {3, nullptr, "SetAudioOutsProcessMasterVolume"}, 15 {3, nullptr, "SetProcessMasterVolume"},
16 {4, nullptr, "GetAudioOutsProcessRecordVolume"}, 16 {4, nullptr, "GetProcessRecordVolume"},
17 {5, nullptr, "SetAudioOutsProcessRecordVolume"}, 17 {5, nullptr, "SetProcessRecordVolume"},
18 }; 18 };
19 // clang-format on 19 // clang-format on
20 20
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 5ed9cb20e..5f51fca9a 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -49,11 +49,11 @@ public:
49 // clang-format off 49 // clang-format off
50 static const FunctionInfo functions[] = { 50 static const FunctionInfo functions[] = {
51 {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, 51 {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
52 {1, &IAudioOut::StartAudioOut, "StartAudioOut"}, 52 {1, &IAudioOut::StartAudioOut, "Start"},
53 {2, &IAudioOut::StopAudioOut, "StopAudioOut"}, 53 {2, &IAudioOut::StopAudioOut, "Stop"},
54 {3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"}, 54 {3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"},
55 {4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"}, 55 {4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"},
56 {5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffer"}, 56 {5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffers"},
57 {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"}, 57 {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"},
58 {7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"}, 58 {7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"},
59 {8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"}, 59 {8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"},
diff --git a/src/core/hle/service/audio/audrec_a.cpp b/src/core/hle/service/audio/audrec_a.cpp
index c5ab7cad4..70fc17ae2 100644
--- a/src/core/hle/service/audio/audrec_a.cpp
+++ b/src/core/hle/service/audio/audrec_a.cpp
@@ -9,8 +9,8 @@ namespace Service::Audio {
9AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"} { 9AudRecA::AudRecA(Core::System& system_) : ServiceFramework{system_, "audrec:a"} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "RequestSuspendFinalOutputRecorders"}, 12 {0, nullptr, "RequestSuspend"},
13 {1, nullptr, "RequestResumeFinalOutputRecorders"}, 13 {1, nullptr, "RequestResume"},
14 }; 14 };
15 // clang-format on 15 // clang-format on
16 16
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/audrec_u.cpp
index eb5c63c62..74a65ccff 100644
--- a/src/core/hle/service/audio/audrec_u.cpp
+++ b/src/core/hle/service/audio/audrec_u.cpp
@@ -13,16 +13,17 @@ public:
13 // clang-format off 13 // clang-format off
14 static const FunctionInfo functions[] = { 14 static const FunctionInfo functions[] = {
15 {0, nullptr, "GetFinalOutputRecorderState"}, 15 {0, nullptr, "GetFinalOutputRecorderState"},
16 {1, nullptr, "StartFinalOutputRecorder"}, 16 {1, nullptr, "Start"},
17 {2, nullptr, "StopFinalOutputRecorder"}, 17 {2, nullptr, "Stop"},
18 {3, nullptr, "AppendFinalOutputRecorderBuffer"}, 18 {3, nullptr, "AppendFinalOutputRecorderBuffer"},
19 {4, nullptr, "RegisterBufferEvent"}, 19 {4, nullptr, "RegisterBufferEvent"},
20 {5, nullptr, "GetReleasedFinalOutputRecorderBuffer"}, 20 {5, nullptr, "GetReleasedFinalOutputRecorderBuffers"},
21 {6, nullptr, "ContainsFinalOutputRecorderBuffer"}, 21 {6, nullptr, "ContainsFinalOutputRecorderBuffer"},
22 {7, nullptr, "GetFinalOutputRecorderBufferEndTime"}, 22 {7, nullptr, "GetFinalOutputRecorderBufferEndTime"},
23 {8, nullptr, "AppendFinalOutputRecorderBufferAuto"}, 23 {8, nullptr, "AppendFinalOutputRecorderBufferAuto"},
24 {9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"}, 24 {9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"},
25 {10, nullptr, "FlushFinalOutputRecorderBuffers"}, 25 {10, nullptr, "FlushFinalOutputRecorderBuffers"},
26 {11, nullptr, "AttachWorkBuffer"},
26 }; 27 };
27 // clang-format on 28 // clang-format on
28 29
diff --git a/src/core/hle/service/audio/audren_a.cpp b/src/core/hle/service/audio/audren_a.cpp
index 5e9f866f0..cf8c34a15 100644
--- a/src/core/hle/service/audio/audren_a.cpp
+++ b/src/core/hle/service/audio/audren_a.cpp
@@ -9,14 +9,14 @@ namespace Service::Audio {
9AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} { 9AudRenA::AudRenA(Core::System& system_) : ServiceFramework{system_, "audren:a"} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "RequestSuspendAudioRenderers"}, 12 {0, nullptr, "RequestSuspend"},
13 {1, nullptr, "RequestResumeAudioRenderers"}, 13 {1, nullptr, "RequestResume"},
14 {2, nullptr, "GetAudioRenderersProcessMasterVolume"}, 14 {2, nullptr, "GetProcessMasterVolume"},
15 {3, nullptr, "SetAudioRenderersProcessMasterVolume"}, 15 {3, nullptr, "SetProcessMasterVolume"},
16 {4, nullptr, "RegisterAppletResourceUserId"}, 16 {4, nullptr, "RegisterAppletResourceUserId"},
17 {5, nullptr, "UnregisterAppletResourceUserId"}, 17 {5, nullptr, "UnregisterAppletResourceUserId"},
18 {6, nullptr, "GetAudioRenderersProcessRecordVolume"}, 18 {6, nullptr, "GetProcessRecordVolume"},
19 {7, nullptr, "SetAudioRenderersProcessRecordVolume"}, 19 {7, nullptr, "SetProcessRecordVolume"},
20 }; 20 };
21 // clang-format on 21 // clang-format on
22 22
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index b2b2ffc5a..572be8e00 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -332,9 +332,9 @@ AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"}
332 // clang-format off 332 // clang-format off
333 static const FunctionInfo functions[] = { 333 static const FunctionInfo functions[] = {
334 {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, 334 {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
335 {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, 335 {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetWorkBufferSize"},
336 {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"}, 336 {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"},
337 {3, &AudRenU::OpenAudioRendererAuto, "OpenAudioRendererAuto"}, 337 {3, &AudRenU::OpenAudioRendererForManualExecution, "OpenAudioRendererForManualExecution"},
338 {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"}, 338 {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
339 }; 339 };
340 // clang-format on 340 // clang-format on
@@ -665,7 +665,7 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) {
665 rb.PushIpcInterface<IAudioDevice>(system, Common::MakeMagic('R', 'E', 'V', '1')); 665 rb.PushIpcInterface<IAudioDevice>(system, Common::MakeMagic('R', 'E', 'V', '1'));
666} 666}
667 667
668void AudRenU::OpenAudioRendererAuto(Kernel::HLERequestContext& ctx) { 668void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) {
669 LOG_DEBUG(Service_Audio, "called"); 669 LOG_DEBUG(Service_Audio, "called");
670 670
671 OpenAudioRendererImpl(ctx); 671 OpenAudioRendererImpl(ctx);
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index d693dc406..37e8b4716 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -25,7 +25,7 @@ private:
25 void OpenAudioRenderer(Kernel::HLERequestContext& ctx); 25 void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
26 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); 26 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
27 void GetAudioDeviceService(Kernel::HLERequestContext& ctx); 27 void GetAudioDeviceService(Kernel::HLERequestContext& ctx);
28 void OpenAudioRendererAuto(Kernel::HLERequestContext& ctx); 28 void OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx);
29 void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); 29 void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx);
30 30
31 void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); 31 void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp
index 94afec1b6..42961d908 100644
--- a/src/core/hle/service/audio/codecctl.cpp
+++ b/src/core/hle/service/audio/codecctl.cpp
@@ -8,19 +8,19 @@ namespace Service::Audio {
8 8
9CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} { 9CodecCtl::CodecCtl(Core::System& system_) : ServiceFramework{system_, "codecctl"} {
10 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
11 {0, nullptr, "InitializeCodecController"}, 11 {0, nullptr, "Initialize"},
12 {1, nullptr, "FinalizeCodecController"}, 12 {1, nullptr, "Finalize"},
13 {2, nullptr, "SleepCodecController"}, 13 {2, nullptr, "Sleep"},
14 {3, nullptr, "WakeCodecController"}, 14 {3, nullptr, "Wake"},
15 {4, nullptr, "SetCodecVolume"}, 15 {4, nullptr, "SetVolume"},
16 {5, nullptr, "GetCodecVolumeMax"}, 16 {5, nullptr, "GetVolumeMax"},
17 {6, nullptr, "GetCodecVolumeMin"}, 17 {6, nullptr, "GetVolumeMin"},
18 {7, nullptr, "SetCodecActiveTarget"}, 18 {7, nullptr, "SetActiveTarget"},
19 {8, nullptr, "GetCodecActiveTarget"}, 19 {8, nullptr, "GetActiveTarget"},
20 {9, nullptr, "BindCodecHeadphoneMicJackInterrupt"}, 20 {9, nullptr, "BindHeadphoneMicJackInterrupt"},
21 {10, nullptr, "IsCodecHeadphoneMicJackInserted"}, 21 {10, nullptr, "IsHeadphoneMicJackInserted"},
22 {11, nullptr, "ClearCodecHeadphoneMicJackInterrupt"}, 22 {11, nullptr, "ClearHeadphoneMicJackInterrupt"},
23 {12, nullptr, "IsCodecDeviceRequested"}, 23 {12, nullptr, "IsRequested"},
24 }; 24 };
25 RegisterHandlers(functions); 25 RegisterHandlers(functions);
26} 26}
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp
index 503109fdd..b68e2c345 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/module.cpp
@@ -155,10 +155,12 @@ public:
155 {30210, nullptr, "SetDeliveryTaskTimer"}, 155 {30210, nullptr, "SetDeliveryTaskTimer"},
156 {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"}, 156 {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"},
157 {90100, nullptr, "EnumerateBackgroundDeliveryTask"}, 157 {90100, nullptr, "EnumerateBackgroundDeliveryTask"},
158 {90101, nullptr, "Unknown90101"},
158 {90200, nullptr, "GetDeliveryList"}, 159 {90200, nullptr, "GetDeliveryList"},
159 {90201, &IBcatService::ClearDeliveryCacheStorage, "ClearDeliveryCacheStorage"}, 160 {90201, &IBcatService::ClearDeliveryCacheStorage, "ClearDeliveryCacheStorage"},
160 {90202, nullptr, "ClearDeliveryTaskSubscriptionStatus"}, 161 {90202, nullptr, "ClearDeliveryTaskSubscriptionStatus"},
161 {90300, nullptr, "GetPushNotificationLog"}, 162 {90300, nullptr, "GetPushNotificationLog"},
163 {90301, nullptr, "Unknown90301"},
162 }; 164 };
163 // clang-format on 165 // clang-format on
164 RegisterHandlers(functions); 166 RegisterHandlers(functions);
diff --git a/src/core/hle/service/bpc/bpc.cpp b/src/core/hle/service/bpc/bpc.cpp
index e4630320e..78e01d8d8 100644
--- a/src/core/hle/service/bpc/bpc.cpp
+++ b/src/core/hle/service/bpc/bpc.cpp
@@ -29,8 +29,8 @@ public:
29 {11, nullptr, "CreateWakeupTimerEx"}, 29 {11, nullptr, "CreateWakeupTimerEx"},
30 {12, nullptr, "GetLastEnabledWakeupTimerType"}, 30 {12, nullptr, "GetLastEnabledWakeupTimerType"},
31 {13, nullptr, "CleanAllWakeupTimers"}, 31 {13, nullptr, "CleanAllWakeupTimers"},
32 {14, nullptr, "Unknown"}, 32 {14, nullptr, "GetPowerButton"},
33 {15, nullptr, "Unknown2"}, 33 {15, nullptr, "SetEnableWakeupTimer"},
34 }; 34 };
35 // clang-format on 35 // clang-format on
36 36
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 17a2ac899..af3a5842d 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -156,6 +156,25 @@ public:
156 {97, nullptr, "RegisterBleHidEvent"}, 156 {97, nullptr, "RegisterBleHidEvent"},
157 {98, nullptr, "SetBleScanParameter"}, 157 {98, nullptr, "SetBleScanParameter"},
158 {99, nullptr, "MoveToSecondaryPiconet"}, 158 {99, nullptr, "MoveToSecondaryPiconet"},
159 {100, nullptr, "IsBluetoothEnabled"},
160 {128, nullptr, "AcquireAudioEvent"},
161 {129, nullptr, "GetAudioEventInfo"},
162 {130, nullptr, "OpenAudioConnection"},
163 {131, nullptr, "CloseAudioConnection"},
164 {132, nullptr, "OpenAudioOut"},
165 {133, nullptr, "CloseAudioOut"},
166 {134, nullptr, "AcquireAudioOutStateChangedEvent"},
167 {135, nullptr, "StartAudioOut"},
168 {136, nullptr, "StopAudioOut"},
169 {137, nullptr, "GetAudioOutState"},
170 {138, nullptr, "GetAudioOutFeedingCodec"},
171 {139, nullptr, "GetAudioOutFeedingParameter"},
172 {140, nullptr, "AcquireAudioOutBufferAvailableEvent"},
173 {141, nullptr, "SendAudioData"},
174 {142, nullptr, "AcquireAudioControlInputStateChangedEvent"},
175 {143, nullptr, "GetAudioControlInputState"},
176 {144, nullptr, "AcquireAudioConnectionStateChangedEvent"},
177 {145, nullptr, "GetConnectedAudioDevice"},
159 {256, nullptr, "IsManufacturingMode"}, 178 {256, nullptr, "IsManufacturingMode"},
160 {257, nullptr, "EmulateBluetoothCrash"}, 179 {257, nullptr, "EmulateBluetoothCrash"},
161 {258, nullptr, "GetBleChannelMap"}, 180 {258, nullptr, "GetBleChannelMap"},
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 9cf2ee92a..d1ebc2388 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -223,6 +223,7 @@ public:
223 {10, nullptr, "GetGattClientDisconnectionReason"}, 223 {10, nullptr, "GetGattClientDisconnectionReason"},
224 {11, nullptr, "GetBleConnectionParameter"}, 224 {11, nullptr, "GetBleConnectionParameter"},
225 {12, nullptr, "GetBleConnectionParameterRequest"}, 225 {12, nullptr, "GetBleConnectionParameterRequest"},
226 {13, nullptr, "Unknown13"},
226 }; 227 };
227 // clang-format on 228 // clang-format on
228 229
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp
index 1fe4f0e14..6220e9f77 100644
--- a/src/core/hle/service/caps/caps_a.cpp
+++ b/src/core/hle/service/caps/caps_a.cpp
@@ -49,6 +49,7 @@ CAPS_A::CAPS_A(Core::System& system_) : ServiceFramework{system_, "caps:a"} {
49 {16, nullptr, "GetAlbumMountResult"}, 49 {16, nullptr, "GetAlbumMountResult"},
50 {17, nullptr, "GetAlbumUsage16"}, 50 {17, nullptr, "GetAlbumUsage16"},
51 {18, nullptr, "Unknown18"}, 51 {18, nullptr, "Unknown18"},
52 {19, nullptr, "Unknown19"},
52 {100, nullptr, "GetAlbumFileCountEx0"}, 53 {100, nullptr, "GetAlbumFileCountEx0"},
53 {101, nullptr, "GetAlbumFileListEx0"}, 54 {101, nullptr, "GetAlbumFileListEx0"},
54 {202, nullptr, "SaveEditedScreenShot"}, 55 {202, nullptr, "SaveEditedScreenShot"},
diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp
index 842316a2e..10b8d54b1 100644
--- a/src/core/hle/service/caps/caps_u.cpp
+++ b/src/core/hle/service/caps/caps_u.cpp
@@ -43,6 +43,7 @@ CAPS_U::CAPS_U(Core::System& system_) : ServiceFramework{system_, "caps:u"} {
43 {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"}, 43 {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
44 {142, &CAPS_U::GetAlbumFileList3AaeAruid, "GetAlbumFileList3AaeAruid"}, 44 {142, &CAPS_U::GetAlbumFileList3AaeAruid, "GetAlbumFileList3AaeAruid"},
45 {143, nullptr, "GetAlbumFileList4AaeUidAruid"}, 45 {143, nullptr, "GetAlbumFileList4AaeUidAruid"},
46 {144, nullptr, "GetAllAlbumFileList3AaeAruid"},
46 {60002, nullptr, "OpenAccessorSessionForApplication"}, 47 {60002, nullptr, "OpenAccessorSessionForApplication"},
47 }; 48 };
48 // clang-format on 49 // clang-format on
diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp
index 4924c61c3..c767926a4 100644
--- a/src/core/hle/service/erpt/erpt.cpp
+++ b/src/core/hle/service/erpt/erpt.cpp
@@ -16,7 +16,7 @@ public:
16 // clang-format off 16 // clang-format off
17 static const FunctionInfo functions[] = { 17 static const FunctionInfo functions[] = {
18 {0, nullptr, "SubmitContext"}, 18 {0, nullptr, "SubmitContext"},
19 {1, nullptr, "CreateReport"}, 19 {1, nullptr, "CreateReportV0"},
20 {2, nullptr, "SetInitialLaunchSettingsCompletionTime"}, 20 {2, nullptr, "SetInitialLaunchSettingsCompletionTime"},
21 {3, nullptr, "ClearInitialLaunchSettingsCompletionTime"}, 21 {3, nullptr, "ClearInitialLaunchSettingsCompletionTime"},
22 {4, nullptr, "UpdatePowerOnTime"}, 22 {4, nullptr, "UpdatePowerOnTime"},
@@ -26,6 +26,11 @@ public:
26 {8, nullptr, "ClearApplicationLaunchTime"}, 26 {8, nullptr, "ClearApplicationLaunchTime"},
27 {9, nullptr, "SubmitAttachment"}, 27 {9, nullptr, "SubmitAttachment"},
28 {10, nullptr, "CreateReportWithAttachments"}, 28 {10, nullptr, "CreateReportWithAttachments"},
29 {11, nullptr, "CreateReport"},
30 {20, nullptr, "RegisterRunningApplet"},
31 {21, nullptr, "UnregisterRunningApplet"},
32 {22, nullptr, "UpdateAppletSuspendedDuration"},
33 {30, nullptr, "InvalidateForcedShutdownDetection"},
29 }; 34 };
30 // clang-format on 35 // clang-format on
31 36
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index 0a6621ef2..a35979053 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -38,7 +38,7 @@ public:
38 {10600, nullptr, "DeclareOpenOnlinePlaySession"}, 38 {10600, nullptr, "DeclareOpenOnlinePlaySession"},
39 {10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"}, 39 {10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"},
40 {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"}, 40 {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"},
41 {10700, nullptr, "GetPlayHistoryRegistrationKey"}, 41 {10700, &IFriendService::GetPlayHistoryRegistrationKey, "GetPlayHistoryRegistrationKey"},
42 {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"}, 42 {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"},
43 {10702, nullptr, "AddPlayHistory"}, 43 {10702, nullptr, "AddPlayHistory"},
44 {11000, nullptr, "GetProfileImageUrl"}, 44 {11000, nullptr, "GetProfileImageUrl"},
@@ -153,6 +153,18 @@ private:
153 rb.Push(RESULT_SUCCESS); 153 rb.Push(RESULT_SUCCESS);
154 } 154 }
155 155
156 void GetPlayHistoryRegistrationKey(Kernel::HLERequestContext& ctx) {
157 IPC::RequestParser rp{ctx};
158 const auto local_play = rp.Pop<bool>();
159 const auto uuid = rp.PopRaw<Common::UUID>();
160
161 LOG_WARNING(Service_Friend, "(STUBBED) called local_play={} uuid={}", local_play,
162 uuid.Format());
163
164 IPC::ResponseBuilder rb{ctx, 2};
165 rb.Push(RESULT_SUCCESS);
166 }
167
156 void GetFriendList(Kernel::HLERequestContext& ctx) { 168 void GetFriendList(Kernel::HLERequestContext& ctx) {
157 IPC::RequestParser rp{ctx}; 169 IPC::RequestParser rp{ctx};
158 const auto friend_offset = rp.Pop<u32>(); 170 const auto friend_offset = rp.Pop<u32>();
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp
index fc77e7286..322125135 100644
--- a/src/core/hle/service/glue/arp.cpp
+++ b/src/core/hle/service/glue/arp.cpp
@@ -41,6 +41,12 @@ ARP_R::ARP_R(Core::System& system_, const ARPManager& manager_)
41 {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"}, 41 {1, &ARP_R::GetApplicationLaunchPropertyWithApplicationId, "GetApplicationLaunchPropertyWithApplicationId"},
42 {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"}, 42 {2, &ARP_R::GetApplicationControlProperty, "GetApplicationControlProperty"},
43 {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"}, 43 {3, &ARP_R::GetApplicationControlPropertyWithApplicationId, "GetApplicationControlPropertyWithApplicationId"},
44 {4, nullptr, "GetApplicationInstanceUnregistrationNotifier"},
45 {5, nullptr, "ListApplicationInstanceId"},
46 {6, nullptr, "GetMicroApplicationInstanceId"},
47 {7, nullptr, "GetApplicationCertificate"},
48 {9998, nullptr, "GetPreomiaApplicationLaunchProperty"},
49 {9999, nullptr, "GetPreomiaApplicationControlProperty"},
44 }; 50 };
45 // clang-format on 51 // clang-format on
46 52
@@ -243,7 +249,8 @@ ARP_W::ARP_W(Core::System& system_, ARPManager& manager_)
243 // clang-format off 249 // clang-format off
244 static const FunctionInfo functions[] = { 250 static const FunctionInfo functions[] = {
245 {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"}, 251 {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"},
246 {1, &ARP_W::DeleteProperties, "DeleteProperties"}, 252 {1, &ARP_W::UnregisterApplicationInstance , "UnregisterApplicationInstance "},
253 {2, nullptr, "AcquireUpdater"},
247 }; 254 };
248 // clang-format on 255 // clang-format on
249 256
@@ -270,7 +277,7 @@ void ARP_W::AcquireRegistrar(Kernel::HLERequestContext& ctx) {
270 rb.PushIpcInterface(registrar); 277 rb.PushIpcInterface(registrar);
271} 278}
272 279
273void ARP_W::DeleteProperties(Kernel::HLERequestContext& ctx) { 280void ARP_W::UnregisterApplicationInstance(Kernel::HLERequestContext& ctx) {
274 IPC::RequestParser rp{ctx}; 281 IPC::RequestParser rp{ctx};
275 const auto process_id = rp.PopRaw<u64>(); 282 const auto process_id = rp.PopRaw<u64>();
276 283
diff --git a/src/core/hle/service/glue/arp.h b/src/core/hle/service/glue/arp.h
index 34b412e26..0df3c5e1f 100644
--- a/src/core/hle/service/glue/arp.h
+++ b/src/core/hle/service/glue/arp.h
@@ -32,7 +32,7 @@ public:
32 32
33private: 33private:
34 void AcquireRegistrar(Kernel::HLERequestContext& ctx); 34 void AcquireRegistrar(Kernel::HLERequestContext& ctx);
35 void DeleteProperties(Kernel::HLERequestContext& ctx); 35 void UnregisterApplicationInstance(Kernel::HLERequestContext& ctx);
36 36
37 ARPManager& manager; 37 ARPManager& manager;
38 std::shared_ptr<IRegistrar> registrar; 38 std::shared_ptr<IRegistrar> registrar;
diff --git a/src/core/hle/service/glue/bgtc.cpp b/src/core/hle/service/glue/bgtc.cpp
index a478b68e1..daecfff15 100644
--- a/src/core/hle/service/glue/bgtc.cpp
+++ b/src/core/hle/service/glue/bgtc.cpp
@@ -2,6 +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 "common/logging/log.h"
6#include "core/core.h"
7#include "core/hle/ipc_helpers.h"
5#include "core/hle/service/glue/bgtc.h" 8#include "core/hle/service/glue/bgtc.h"
6 9
7namespace Service::Glue { 10namespace Service::Glue {
@@ -9,6 +12,26 @@ namespace Service::Glue {
9BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} { 12BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} {
10 // clang-format off 13 // clang-format off
11 static const FunctionInfo functions[] = { 14 static const FunctionInfo functions[] = {
15 {100, &BGTC_T::OpenTaskService, "OpenTaskService"},
16 };
17 // clang-format on
18
19 RegisterHandlers(functions);
20}
21
22BGTC_T::~BGTC_T() = default;
23
24void BGTC_T::OpenTaskService(Kernel::HLERequestContext& ctx) {
25 LOG_DEBUG(Service_BGTC, "called");
26
27 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
28 rb.Push(RESULT_SUCCESS);
29 rb.PushIpcInterface<ITaskService>(system);
30}
31
32ITaskService::ITaskService(Core::System& system_) : ServiceFramework{system_, "ITaskService"} {
33 // clang-format off
34 static const FunctionInfo functions[] = {
12 {1, nullptr, "NotifyTaskStarting"}, 35 {1, nullptr, "NotifyTaskStarting"},
13 {2, nullptr, "NotifyTaskFinished"}, 36 {2, nullptr, "NotifyTaskFinished"},
14 {3, nullptr, "GetTriggerEvent"}, 37 {3, nullptr, "GetTriggerEvent"},
@@ -20,16 +43,18 @@ BGTC_T::BGTC_T(Core::System& system_) : ServiceFramework{system_, "bgtc:t"} {
20 {13, nullptr, "UnscheduleTask"}, 43 {13, nullptr, "UnscheduleTask"},
21 {14, nullptr, "GetScheduleEvent"}, 44 {14, nullptr, "GetScheduleEvent"},
22 {15, nullptr, "SchedulePeriodicTask"}, 45 {15, nullptr, "SchedulePeriodicTask"},
46 {16, nullptr, "Unknown16"},
23 {101, nullptr, "GetOperationMode"}, 47 {101, nullptr, "GetOperationMode"},
24 {102, nullptr, "WillDisconnectNetworkWhenEnteringSleep"}, 48 {102, nullptr, "WillDisconnectNetworkWhenEnteringSleep"},
25 {103, nullptr, "WillStayHalfAwakeInsteadSleep"}, 49 {103, nullptr, "WillStayHalfAwakeInsteadSleep"},
50 {200, nullptr, "Unknown200"},
26 }; 51 };
27 // clang-format on 52 // clang-format on
28 53
29 RegisterHandlers(functions); 54 RegisterHandlers(functions);
30} 55}
31 56
32BGTC_T::~BGTC_T() = default; 57ITaskService::~ITaskService() = default;
33 58
34BGTC_SC::BGTC_SC(Core::System& system_) : ServiceFramework{system_, "bgtc:sc"} { 59BGTC_SC::BGTC_SC(Core::System& system_) : ServiceFramework{system_, "bgtc:sc"} {
35 // clang-format off 60 // clang-format off
diff --git a/src/core/hle/service/glue/bgtc.h b/src/core/hle/service/glue/bgtc.h
index 906116ba6..4c0142fd5 100644
--- a/src/core/hle/service/glue/bgtc.h
+++ b/src/core/hle/service/glue/bgtc.h
@@ -16,6 +16,14 @@ class BGTC_T final : public ServiceFramework<BGTC_T> {
16public: 16public:
17 explicit BGTC_T(Core::System& system_); 17 explicit BGTC_T(Core::System& system_);
18 ~BGTC_T() override; 18 ~BGTC_T() override;
19
20 void OpenTaskService(Kernel::HLERequestContext& ctx);
21};
22
23class ITaskService final : public ServiceFramework<ITaskService> {
24public:
25 explicit ITaskService(Core::System& system_);
26 ~ITaskService() override;
19}; 27};
20 28
21class BGTC_SC final : public ServiceFramework<BGTC_SC> { 29class BGTC_SC final : public ServiceFramework<BGTC_SC> {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 1df62f98e..673db68c7 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -1138,6 +1138,10 @@ void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_prot
1138 unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled; 1138 unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled;
1139} 1139}
1140 1140
1141void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
1142 analog_stick_use_center_clamp = use_center_clamp;
1143}
1144
1141void Controller_NPad::ClearAllConnectedControllers() { 1145void Controller_NPad::ClearAllConnectedControllers() {
1142 for (auto& controller : connected_controllers) { 1146 for (auto& controller : connected_controllers) {
1143 if (controller.is_connected && controller.type != NPadControllerType::None) { 1147 if (controller.is_connected && controller.type != NPadControllerType::None) {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index bc2e6779d..873a0a1e2 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -219,6 +219,7 @@ public:
219 LedPattern GetLedPattern(u32 npad_id); 219 LedPattern GetLedPattern(u32 npad_id);
220 bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const; 220 bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
221 void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id); 221 void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
222 void SetAnalogStickUseCenterClamp(bool use_center_clamp);
222 void ClearAllConnectedControllers(); 223 void ClearAllConnectedControllers();
223 void DisconnectAllConnectedControllers(); 224 void DisconnectAllConnectedControllers();
224 void ConnectAllDisconnectedControllers(); 225 void ConnectAllDisconnectedControllers();
@@ -577,6 +578,7 @@ private:
577 std::array<std::array<bool, 2>, 10> vibration_devices_mounted{}; 578 std::array<std::array<bool, 2>, 10> vibration_devices_mounted{};
578 std::array<ControllerHolder, 10> connected_controllers{}; 579 std::array<ControllerHolder, 10> connected_controllers{};
579 std::array<bool, 10> unintended_home_button_input_protection{}; 580 std::array<bool, 10> unintended_home_button_input_protection{};
581 bool analog_stick_use_center_clamp{};
580 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; 582 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
581 bool sixaxis_sensors_enabled{true}; 583 bool sixaxis_sensors_enabled{true};
582 f32 sixaxis_fusion_parameter1{}; 584 f32 sixaxis_fusion_parameter1{};
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ba27bbb05..a1a779cc0 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -263,7 +263,7 @@ Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} {
263 {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"}, 263 {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
264 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"}, 264 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
265 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, 265 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
266 {134, nullptr, "SetNpadAnalogStickUseCenterClamp"}, 266 {134, &Hid::SetNpadAnalogStickUseCenterClamp, "SetNpadAnalogStickUseCenterClamp"},
267 {135, nullptr, "SetNpadCaptureButtonAssignment"}, 267 {135, nullptr, "SetNpadCaptureButtonAssignment"},
268 {136, nullptr, "ClearNpadCaptureButtonAssignment"}, 268 {136, nullptr, "ClearNpadCaptureButtonAssignment"},
269 {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"}, 269 {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
@@ -278,6 +278,7 @@ Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} {
278 {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, 278 {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
279 {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, 279 {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"},
280 {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, 280 {211, &Hid::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"},
281 {212, nullptr, "SendVibrationValueInBool"},
281 {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, 282 {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
282 {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, 283 {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
283 {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, 284 {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"},
@@ -1087,6 +1088,27 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c
1087 rb.Push(RESULT_SUCCESS); 1088 rb.Push(RESULT_SUCCESS);
1088} 1089}
1089 1090
1091void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
1092 IPC::RequestParser rp{ctx};
1093 struct Parameters {
1094 bool analog_stick_use_center_clamp;
1095 u64 applet_resource_user_id;
1096 };
1097 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
1098
1099 const auto parameters{rp.PopRaw<Parameters>()};
1100
1101 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1102 .SetAnalogStickUseCenterClamp(parameters.analog_stick_use_center_clamp);
1103
1104 LOG_WARNING(Service_HID,
1105 "(STUBBED) called, analog_stick_use_center_clamp={}, applet_resource_user_id={}",
1106 parameters.analog_stick_use_center_clamp, parameters.applet_resource_user_id);
1107
1108 IPC::ResponseBuilder rb{ctx, 2};
1109 rb.Push(RESULT_SUCCESS);
1110}
1111
1090void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { 1112void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
1091 IPC::RequestParser rp{ctx}; 1113 IPC::RequestParser rp{ctx};
1092 const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()}; 1114 const auto vibration_device_handle{rp.PopRaw<Controller_NPad::DeviceHandle>()};
@@ -1553,6 +1575,7 @@ public:
1553 {11, nullptr, "SetTouchScreenAutoPilotState"}, 1575 {11, nullptr, "SetTouchScreenAutoPilotState"},
1554 {12, nullptr, "UnsetTouchScreenAutoPilotState"}, 1576 {12, nullptr, "UnsetTouchScreenAutoPilotState"},
1555 {13, nullptr, "GetTouchScreenConfiguration"}, 1577 {13, nullptr, "GetTouchScreenConfiguration"},
1578 {14, nullptr, "ProcessTouchScreenAutoTune"},
1556 {20, nullptr, "DeactivateMouse"}, 1579 {20, nullptr, "DeactivateMouse"},
1557 {21, nullptr, "SetMouseAutoPilotState"}, 1580 {21, nullptr, "SetMouseAutoPilotState"},
1558 {22, nullptr, "UnsetMouseAutoPilotState"}, 1581 {22, nullptr, "UnsetMouseAutoPilotState"},
@@ -1562,6 +1585,7 @@ public:
1562 {50, nullptr, "DeactivateXpad"}, 1585 {50, nullptr, "DeactivateXpad"},
1563 {51, nullptr, "SetXpadAutoPilotState"}, 1586 {51, nullptr, "SetXpadAutoPilotState"},
1564 {52, nullptr, "UnsetXpadAutoPilotState"}, 1587 {52, nullptr, "UnsetXpadAutoPilotState"},
1588 {53, nullptr, "DeactivateJoyXpad"},
1565 {60, nullptr, "ClearNpadSystemCommonPolicy"}, 1589 {60, nullptr, "ClearNpadSystemCommonPolicy"},
1566 {61, nullptr, "DeactivateNpad"}, 1590 {61, nullptr, "DeactivateNpad"},
1567 {62, nullptr, "ForceDisconnectNpad"}, 1591 {62, nullptr, "ForceDisconnectNpad"},
@@ -1632,6 +1656,11 @@ public:
1632 {244, nullptr, "RequestKuinaFirmwareVersion"}, 1656 {244, nullptr, "RequestKuinaFirmwareVersion"},
1633 {245, nullptr, "GetKuinaFirmwareVersion"}, 1657 {245, nullptr, "GetKuinaFirmwareVersion"},
1634 {246, nullptr, "GetVidPid"}, 1658 {246, nullptr, "GetVidPid"},
1659 {247, nullptr, "GetAnalogStickCalibrationValue"},
1660 {248, nullptr, "GetUniquePadIdsFull"},
1661 {249, nullptr, "ConnectUniquePad"},
1662 {250, nullptr, "IsVirtual"},
1663 {251, nullptr, "GetAnalogStickModuleParam"},
1635 {301, nullptr, "GetAbstractedPadHandles"}, 1664 {301, nullptr, "GetAbstractedPadHandles"},
1636 {302, nullptr, "GetAbstractedPadState"}, 1665 {302, nullptr, "GetAbstractedPadState"},
1637 {303, nullptr, "GetAbstractedPadsState"}, 1666 {303, nullptr, "GetAbstractedPadsState"},
@@ -1652,12 +1681,16 @@ public:
1652 {401, nullptr, "DisableRailDeviceFiltering"}, 1681 {401, nullptr, "DisableRailDeviceFiltering"},
1653 {402, nullptr, "EnableWiredPairing"}, 1682 {402, nullptr, "EnableWiredPairing"},
1654 {403, nullptr, "EnableShipmentModeAutoClear"}, 1683 {403, nullptr, "EnableShipmentModeAutoClear"},
1684 {404, nullptr, "SetRailEnabled"},
1655 {500, nullptr, "SetFactoryInt"}, 1685 {500, nullptr, "SetFactoryInt"},
1656 {501, nullptr, "IsFactoryBootEnabled"}, 1686 {501, nullptr, "IsFactoryBootEnabled"},
1657 {550, nullptr, "SetAnalogStickModelDataTemporarily"}, 1687 {550, nullptr, "SetAnalogStickModelDataTemporarily"},
1658 {551, nullptr, "GetAnalogStickModelData"}, 1688 {551, nullptr, "GetAnalogStickModelData"},
1659 {552, nullptr, "ResetAnalogStickModelData"}, 1689 {552, nullptr, "ResetAnalogStickModelData"},
1660 {600, nullptr, "ConvertPadState"}, 1690 {600, nullptr, "ConvertPadState"},
1691 {650, nullptr, "AddButtonPlayData"},
1692 {651, nullptr, "StartButtonPlayData"},
1693 {652, nullptr, "StopButtonPlayData"},
1661 {2000, nullptr, "DeactivateDigitizer"}, 1694 {2000, nullptr, "DeactivateDigitizer"},
1662 {2001, nullptr, "SetDigitizerAutoPilotState"}, 1695 {2001, nullptr, "SetDigitizerAutoPilotState"},
1663 {2002, nullptr, "UnsetDigitizerAutoPilotState"}, 1696 {2002, nullptr, "UnsetDigitizerAutoPilotState"},
@@ -1689,6 +1722,8 @@ public:
1689 {215, nullptr, "IsNfcActivated"}, 1722 {215, nullptr, "IsNfcActivated"},
1690 {230, nullptr, "AcquireIrSensorEventHandle"}, 1723 {230, nullptr, "AcquireIrSensorEventHandle"},
1691 {231, nullptr, "ActivateIrSensor"}, 1724 {231, nullptr, "ActivateIrSensor"},
1725 {232, nullptr, "GetIrSensorState"},
1726 {233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
1692 {301, nullptr, "ActivateNpadSystem"}, 1727 {301, nullptr, "ActivateNpadSystem"},
1693 {303, nullptr, "ApplyNpadSystemCommonPolicy"}, 1728 {303, nullptr, "ApplyNpadSystemCommonPolicy"},
1694 {304, nullptr, "EnableAssigningSingleOnSlSrPress"}, 1729 {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
@@ -1703,9 +1738,16 @@ public:
1703 {313, nullptr, "GetNpadCaptureButtonAssignment"}, 1738 {313, nullptr, "GetNpadCaptureButtonAssignment"},
1704 {314, nullptr, "GetAppletFooterUiType"}, 1739 {314, nullptr, "GetAppletFooterUiType"},
1705 {315, nullptr, "GetAppletDetailedUiType"}, 1740 {315, nullptr, "GetAppletDetailedUiType"},
1741 {316, nullptr, "GetNpadInterfaceType"},
1742 {317, nullptr, "GetNpadLeftRightInterfaceType"},
1743 {318, nullptr, "HasBattery"},
1744 {319, nullptr, "HasLeftRightBattery"},
1706 {321, nullptr, "GetUniquePadsFromNpad"}, 1745 {321, nullptr, "GetUniquePadsFromNpad"},
1707 {322, nullptr, "GetIrSensorState"}, 1746 {322, nullptr, "GetIrSensorState"},
1708 {323, nullptr, "GetXcdHandleForNpadWithIrSensor"}, 1747 {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
1748 {324, nullptr, "GetUniquePadButtonSet"},
1749 {325, nullptr, "GetUniquePadColor"},
1750 {326, nullptr, "GetUniquePadAppletDetailedUiType"},
1709 {500, nullptr, "SetAppletResourceUserId"}, 1751 {500, nullptr, "SetAppletResourceUserId"},
1710 {501, nullptr, "RegisterAppletResourceUserId"}, 1752 {501, nullptr, "RegisterAppletResourceUserId"},
1711 {502, nullptr, "UnregisterAppletResourceUserId"}, 1753 {502, nullptr, "UnregisterAppletResourceUserId"},
@@ -1716,10 +1758,13 @@ public:
1716 {511, nullptr, "GetVibrationMasterVolume"}, 1758 {511, nullptr, "GetVibrationMasterVolume"},
1717 {512, nullptr, "BeginPermitVibrationSession"}, 1759 {512, nullptr, "BeginPermitVibrationSession"},
1718 {513, nullptr, "EndPermitVibrationSession"}, 1760 {513, nullptr, "EndPermitVibrationSession"},
1761 {514, nullptr, "Unknown514"},
1719 {520, nullptr, "EnableHandheldHids"}, 1762 {520, nullptr, "EnableHandheldHids"},
1720 {521, nullptr, "DisableHandheldHids"}, 1763 {521, nullptr, "DisableHandheldHids"},
1721 {522, nullptr, "SetJoyConRailEnabled"}, 1764 {522, nullptr, "SetJoyConRailEnabled"},
1722 {523, nullptr, "IsJoyConRailEnabled"}, 1765 {523, nullptr, "IsJoyConRailEnabled"},
1766 {524, nullptr, "IsHandheldHidsEnabled"},
1767 {525, nullptr, "IsJoyConAttachedOnAllRail"},
1723 {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"}, 1768 {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
1724 {541, nullptr, "GetPlayReportControllerUsages"}, 1769 {541, nullptr, "GetPlayReportControllerUsages"},
1725 {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"}, 1770 {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
@@ -1795,6 +1840,65 @@ public:
1795 {1154, nullptr, "IsFirmwareAvailableForNotification"}, 1840 {1154, nullptr, "IsFirmwareAvailableForNotification"},
1796 {1155, nullptr, "SetForceHandheldStyleVibration"}, 1841 {1155, nullptr, "SetForceHandheldStyleVibration"},
1797 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, 1842 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
1843 {1157, nullptr, "CancelConnectionTrigger"},
1844 {1200, nullptr, "IsButtonConfigSupported"},
1845 {1201, nullptr, "IsButtonConfigEmbeddedSupported"},
1846 {1202, nullptr, "DeleteButtonConfig"},
1847 {1203, nullptr, "DeleteButtonConfigEmbedded"},
1848 {1204, nullptr, "SetButtonConfigEnabled"},
1849 {1205, nullptr, "SetButtonConfigEmbeddedEnabled"},
1850 {1206, nullptr, "IsButtonConfigEnabled"},
1851 {1207, nullptr, "IsButtonConfigEmbeddedEnabled"},
1852 {1208, nullptr, "SetButtonConfigEmbedded"},
1853 {1209, nullptr, "SetButtonConfigFull"},
1854 {1210, nullptr, "SetButtonConfigLeft"},
1855 {1211, nullptr, "SetButtonConfigRight"},
1856 {1212, nullptr, "GetButtonConfigEmbedded"},
1857 {1213, nullptr, "GetButtonConfigFull"},
1858 {1214, nullptr, "GetButtonConfigLeft"},
1859 {1215, nullptr, "GetButtonConfigRight"},
1860 {1250, nullptr, "IsCustomButtonConfigSupported"},
1861 {1251, nullptr, "IsDefaultButtonConfigEmbedded"},
1862 {1252, nullptr, "IsDefaultButtonConfigFull"},
1863 {1253, nullptr, "IsDefaultButtonConfigLeft"},
1864 {1254, nullptr, "IsDefaultButtonConfigRight"},
1865 {1255, nullptr, "IsButtonConfigStorageEmbeddedEmpty"},
1866 {1256, nullptr, "IsButtonConfigStorageFullEmpty"},
1867 {1257, nullptr, "IsButtonConfigStorageLeftEmpty"},
1868 {1258, nullptr, "IsButtonConfigStorageRightEmpty"},
1869 {1259, nullptr, "GetButtonConfigStorageEmbeddedDeprecated"},
1870 {1260, nullptr, "GetButtonConfigStorageFullDeprecated"},
1871 {1261, nullptr, "GetButtonConfigStorageLeftDeprecated"},
1872 {1262, nullptr, "GetButtonConfigStorageRightDeprecated"},
1873 {1263, nullptr, "SetButtonConfigStorageEmbeddedDeprecated"},
1874 {1264, nullptr, "SetButtonConfigStorageFullDeprecated"},
1875 {1265, nullptr, "SetButtonConfigStorageLeftDeprecated"},
1876 {1266, nullptr, "SetButtonConfigStorageRightDeprecated"},
1877 {1267, nullptr, "DeleteButtonConfigStorageEmbedded"},
1878 {1268, nullptr, "DeleteButtonConfigStorageFull"},
1879 {1269, nullptr, "DeleteButtonConfigStorageLeft"},
1880 {1270, nullptr, "DeleteButtonConfigStorageRight"},
1881 {1271, nullptr, "IsUsingCustomButtonConfig"},
1882 {1272, nullptr, "IsAnyCustomButtonConfigEnabled"},
1883 {1273, nullptr, "SetAllCustomButtonConfigEnabled"},
1884 {1274, nullptr, "SetDefaultButtonConfig"},
1885 {1275, nullptr, "SetAllDefaultButtonConfig"},
1886 {1276, nullptr, "SetHidButtonConfigEmbedded"},
1887 {1277, nullptr, "SetHidButtonConfigFull"},
1888 {1278, nullptr, "SetHidButtonConfigLeft"},
1889 {1279, nullptr, "SetHidButtonConfigRight"},
1890 {1280, nullptr, "GetHidButtonConfigEmbedded"},
1891 {1281, nullptr, "GetHidButtonConfigFull"},
1892 {1282, nullptr, "GetHidButtonConfigLeft"},
1893 {1283, nullptr, "GetHidButtonConfigRight"},
1894 {1284, nullptr, "GetButtonConfigStorageEmbedded"},
1895 {1285, nullptr, "GetButtonConfigStorageFull"},
1896 {1286, nullptr, "GetButtonConfigStorageLeft"},
1897 {1287, nullptr, "GetButtonConfigStorageRight"},
1898 {1288, nullptr, "SetButtonConfigStorageEmbedded"},
1899 {1289, nullptr, "SetButtonConfigStorageFull"},
1900 {1290, nullptr, "DeleteButtonConfigStorageRight"},
1901 {1291, nullptr, "DeleteButtonConfigStorageRight"},
1798 }; 1902 };
1799 // clang-format on 1903 // clang-format on
1800 1904
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 36ed228c8..c2bdd39a3 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -129,6 +129,7 @@ private:
129 void SwapNpadAssignment(Kernel::HLERequestContext& ctx); 129 void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
130 void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx); 130 void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx);
131 void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx); 131 void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx);
132 void SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx);
132 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); 133 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx);
133 void SendVibrationValue(Kernel::HLERequestContext& ctx); 134 void SendVibrationValue(Kernel::HLERequestContext& ctx);
134 void GetActualVibrationValue(Kernel::HLERequestContext& ctx); 135 void GetActualVibrationValue(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/hid/xcd.cpp b/src/core/hle/service/hid/xcd.cpp
index 43a8840d0..b1efa3d05 100644
--- a/src/core/hle/service/hid/xcd.cpp
+++ b/src/core/hle/service/hid/xcd.cpp
@@ -28,6 +28,8 @@ XCD_SYS::XCD_SYS(Core::System& system_) : ServiceFramework{system_, "xcd:sys"} {
28 {20, nullptr, "StartMifareWrite"}, 28 {20, nullptr, "StartMifareWrite"},
29 {101, nullptr, "GetAwakeTriggerReasonForLeftRail"}, 29 {101, nullptr, "GetAwakeTriggerReasonForLeftRail"},
30 {102, nullptr, "GetAwakeTriggerReasonForRightRail"}, 30 {102, nullptr, "GetAwakeTriggerReasonForRightRail"},
31 {103, nullptr, "GetAwakeTriggerBatteryLevelTransitionForLeftRail"},
32 {104, nullptr, "GetAwakeTriggerBatteryLevelTransitionForRightRail"},
31 }; 33 };
32 // clang-format on 34 // clang-format on
33 35
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index d111c1357..c8bc60ad1 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -118,9 +118,9 @@ public:
118 explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "ldr:dmnt"} { 118 explicit DebugMonitor(Core::System& system_) : ServiceFramework{system_, "ldr:dmnt"} {
119 // clang-format off 119 // clang-format off
120 static const FunctionInfo functions[] = { 120 static const FunctionInfo functions[] = {
121 {0, nullptr, "AddProcessToDebugLaunchQueue"}, 121 {0, nullptr, "SetProgramArgument"},
122 {1, nullptr, "ClearDebugLaunchQueue"}, 122 {1, nullptr, "FlushArguments"},
123 {2, nullptr, "GetNsoInfos"}, 123 {2, nullptr, "GetProcessModuleInfo"},
124 }; 124 };
125 // clang-format on 125 // clang-format on
126 126
@@ -135,8 +135,8 @@ public:
135 static const FunctionInfo functions[] = { 135 static const FunctionInfo functions[] = {
136 {0, nullptr, "CreateProcess"}, 136 {0, nullptr, "CreateProcess"},
137 {1, nullptr, "GetProgramInfo"}, 137 {1, nullptr, "GetProgramInfo"},
138 {2, nullptr, "RegisterTitle"}, 138 {2, nullptr, "PinProgram"},
139 {3, nullptr, "UnregisterTitle"}, 139 {3, nullptr, "UnpinProgram"},
140 {4, nullptr, "SetEnabledProgramVerification"}, 140 {4, nullptr, "SetEnabledProgramVerification"},
141 }; 141 };
142 // clang-format on 142 // clang-format on
@@ -150,8 +150,8 @@ public:
150 explicit Shell(Core::System& system_) : ServiceFramework{system_, "ldr:shel"} { 150 explicit Shell(Core::System& system_) : ServiceFramework{system_, "ldr:shel"} {
151 // clang-format off 151 // clang-format off
152 static const FunctionInfo functions[] = { 152 static const FunctionInfo functions[] = {
153 {0, nullptr, "AddProcessToLaunchQueue"}, 153 {0, nullptr, "SetProgramArgument"},
154 {1, nullptr, "ClearLaunchQueue"}, 154 {1, nullptr, "FlushArguments"},
155 }; 155 };
156 // clang-format on 156 // clang-format on
157 157
@@ -164,19 +164,19 @@ public:
164 explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} { 164 explicit RelocatableObject(Core::System& system_) : ServiceFramework{system_, "ldr:ro"} {
165 // clang-format off 165 // clang-format off
166 static const FunctionInfo functions[] = { 166 static const FunctionInfo functions[] = {
167 {0, &RelocatableObject::LoadNro, "LoadNro"}, 167 {0, &RelocatableObject::LoadModule, "LoadModule"},
168 {1, &RelocatableObject::UnloadNro, "UnloadNro"}, 168 {1, &RelocatableObject::UnloadModule, "UnloadModule"},
169 {2, &RelocatableObject::LoadNrr, "LoadNrr"}, 169 {2, &RelocatableObject::RegisterModuleInfo, "RegisterModuleInfo"},
170 {3, &RelocatableObject::UnloadNrr, "UnloadNrr"}, 170 {3, &RelocatableObject::UnregisterModuleInfo, "UnregisterModuleInfo"},
171 {4, &RelocatableObject::Initialize, "Initialize"}, 171 {4, &RelocatableObject::Initialize, "Initialize"},
172 {10, nullptr, "LoadNrrEx"}, 172 {10, nullptr, "RegisterModuleInfo2"},
173 }; 173 };
174 // clang-format on 174 // clang-format on
175 175
176 RegisterHandlers(functions); 176 RegisterHandlers(functions);
177 } 177 }
178 178
179 void LoadNrr(Kernel::HLERequestContext& ctx) { 179 void RegisterModuleInfo(Kernel::HLERequestContext& ctx) {
180 struct Parameters { 180 struct Parameters {
181 u64_le process_id; 181 u64_le process_id;
182 u64_le nrr_address; 182 u64_le nrr_address;
@@ -273,7 +273,7 @@ public:
273 rb.Push(RESULT_SUCCESS); 273 rb.Push(RESULT_SUCCESS);
274 } 274 }
275 275
276 void UnloadNrr(Kernel::HLERequestContext& ctx) { 276 void UnregisterModuleInfo(Kernel::HLERequestContext& ctx) {
277 IPC::RequestParser rp{ctx}; 277 IPC::RequestParser rp{ctx};
278 const auto pid = rp.Pop<u64>(); 278 const auto pid = rp.Pop<u64>();
279 const auto nrr_address = rp.Pop<VAddr>(); 279 const auto nrr_address = rp.Pop<VAddr>();
@@ -408,7 +408,7 @@ public:
408 data_start, bss_end_addr - data_start, Kernel::KMemoryPermission::ReadAndWrite); 408 data_start, bss_end_addr - data_start, Kernel::KMemoryPermission::ReadAndWrite);
409 } 409 }
410 410
411 void LoadNro(Kernel::HLERequestContext& ctx) { 411 void LoadModule(Kernel::HLERequestContext& ctx) {
412 struct Parameters { 412 struct Parameters {
413 u64_le process_id; 413 u64_le process_id;
414 u64_le image_address; 414 u64_le image_address;
@@ -546,7 +546,7 @@ public:
546 return RESULT_SUCCESS; 546 return RESULT_SUCCESS;
547 } 547 }
548 548
549 void UnloadNro(Kernel::HLERequestContext& ctx) { 549 void UnloadModule(Kernel::HLERequestContext& ctx) {
550 if (!initialized) { 550 if (!initialized) {
551 LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!"); 551 LOG_ERROR(Service_LDR, "LDR:RO not initialized before use!");
552 IPC::ResponseBuilder rb{ctx, 2}; 552 IPC::ResponseBuilder rb{ctx, 2};
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index f3be0b878..fee360ab9 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -125,51 +125,51 @@ public:
125 {39, nullptr, "PrepareShutdown"}, 125 {39, nullptr, "PrepareShutdown"},
126 {40, nullptr, "ListApplyDeltaTask"}, 126 {40, nullptr, "ListApplyDeltaTask"},
127 {41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"}, 127 {41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"},
128 {42, nullptr, "Unknown42"}, 128 {42, nullptr, "CreateApplyDeltaTaskFromDownloadTask"},
129 {43, nullptr, "Unknown43"}, 129 {43, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
130 {44, nullptr, "Unknown44"}, 130 {44, nullptr, "GetApplyDeltaTaskRequiredStorage"},
131 {45, nullptr, "Unknown45"}, 131 {45, nullptr, "CalculateNetworkInstallTaskContentsSize"},
132 {46, nullptr, "Unknown46"}, 132 {46, nullptr, "PrepareShutdownForSystemUpdate"},
133 {47, nullptr, "Unknown47"}, 133 {47, nullptr, "FindMaxRequiredApplicationVersionOfTask"},
134 {48, nullptr, "Unknown48"}, 134 {48, nullptr, "CommitNetworkInstallTaskPartially"},
135 {49, nullptr, "Unknown49"}, 135 {49, nullptr, "ListNetworkInstallTaskCommittedContentMeta"},
136 {50, nullptr, "Unknown50"}, 136 {50, nullptr, "ListNetworkInstallTaskNotCommittedContentMeta"},
137 {51, nullptr, "Unknown51"}, 137 {51, nullptr, "FindMaxRequiredSystemVersionOfTask"},
138 {52, nullptr, "Unknown52"}, 138 {52, nullptr, "GetNetworkInstallTaskErrorContext"},
139 {53, nullptr, "Unknown53"}, 139 {53, nullptr, "CreateLocalCommunicationReceiveApplicationTask"},
140 {54, nullptr, "Unknown54"}, 140 {54, nullptr, "DestroyLocalCommunicationReceiveApplicationTask"},
141 {55, nullptr, "Unknown55"}, 141 {55, nullptr, "ListLocalCommunicationReceiveApplicationTask"},
142 {56, nullptr, "Unknown56"}, 142 {56, nullptr, "RequestLocalCommunicationReceiveApplicationTaskRun"},
143 {57, nullptr, "Unknown57"}, 143 {57, nullptr, "GetLocalCommunicationReceiveApplicationTaskInfo"},
144 {58, nullptr, "Unknown58"}, 144 {58, nullptr, "CommitLocalCommunicationReceiveApplicationTask"},
145 {59, nullptr, "Unknown59"}, 145 {59, nullptr, "ListLocalCommunicationReceiveApplicationTaskContentMeta"},
146 {60, nullptr, "Unknown60"}, 146 {60, nullptr, "CreateLocalCommunicationSendApplicationTask"},
147 {61, nullptr, "Unknown61"}, 147 {61, nullptr, "RequestLocalCommunicationSendApplicationTaskRun"},
148 {62, nullptr, "Unknown62"}, 148 {62, nullptr, "GetLocalCommunicationReceiveApplicationTaskErrorContext"},
149 {63, nullptr, "Unknown63"}, 149 {63, nullptr, "GetLocalCommunicationSendApplicationTaskInfo"},
150 {64, nullptr, "Unknown64"}, 150 {64, nullptr, "DestroyLocalCommunicationSendApplicationTask"},
151 {65, nullptr, "Unknown65"}, 151 {65, nullptr, "GetLocalCommunicationSendApplicationTaskErrorContext"},
152 {66, nullptr, "Unknown66"}, 152 {66, nullptr, "CalculateLocalCommunicationReceiveApplicationTaskRequiredSize"},
153 {67, nullptr, "Unknown67"}, 153 {67, nullptr, "ListApplicationLocalCommunicationReceiveApplicationTask"},
154 {68, nullptr, "Unknown68"}, 154 {68, nullptr, "ListApplicationLocalCommunicationSendApplicationTask"},
155 {69, nullptr, "Unknown69"}, 155 {69, nullptr, "CreateLocalCommunicationReceiveSystemUpdateTask"},
156 {70, nullptr, "Unknown70"}, 156 {70, nullptr, "DestroyLocalCommunicationReceiveSystemUpdateTask"},
157 {71, nullptr, "Unknown71"}, 157 {71, nullptr, "ListLocalCommunicationReceiveSystemUpdateTask"},
158 {72, nullptr, "Unknown72"}, 158 {72, nullptr, "RequestLocalCommunicationReceiveSystemUpdateTaskRun"},
159 {73, nullptr, "Unknown73"}, 159 {73, nullptr, "GetLocalCommunicationReceiveSystemUpdateTaskInfo"},
160 {74, nullptr, "Unknown74"}, 160 {74, nullptr, "CommitLocalCommunicationReceiveSystemUpdateTask"},
161 {75, nullptr, "Unknown75"}, 161 {75, nullptr, "GetLocalCommunicationReceiveSystemUpdateTaskErrorContext"},
162 {76, nullptr, "Unknown76"}, 162 {76, nullptr, "CreateLocalCommunicationSendSystemUpdateTask"},
163 {77, nullptr, "Unknown77"}, 163 {77, nullptr, "RequestLocalCommunicationSendSystemUpdateTaskRun"},
164 {78, nullptr, "Unknown78"}, 164 {78, nullptr, "GetLocalCommunicationSendSystemUpdateTaskInfo"},
165 {79, nullptr, "Unknown79"}, 165 {79, nullptr, "DestroyLocalCommunicationSendSystemUpdateTask"},
166 {80, nullptr, "Unknown80"}, 166 {80, nullptr, "GetLocalCommunicationSendSystemUpdateTaskErrorContext"},
167 {81, nullptr, "Unknown81"}, 167 {81, nullptr, "ListLocalCommunicationSendSystemUpdateTask"},
168 {82, nullptr, "Unknown82"}, 168 {82, nullptr, "GetReceivedSystemDataPath"},
169 {83, nullptr, "Unknown83"}, 169 {83, nullptr, "CalculateApplyDeltaTaskOccupiedSize"},
170 {84, nullptr, "Unknown84"}, 170 {84, nullptr, "Unknown84"},
171 {85, nullptr, "Unknown85"}, 171 {85, nullptr, "ListNetworkInstallTaskContentMetaFromInstallMeta"},
172 {86, nullptr, "Unknown86"}, 172 {86, nullptr, "ListNetworkInstallTaskOccupiedSize"},
173 {87, nullptr, "Unknown87"}, 173 {87, nullptr, "Unknown87"},
174 {88, nullptr, "Unknown88"}, 174 {88, nullptr, "Unknown88"},
175 {89, nullptr, "Unknown89"}, 175 {89, nullptr, "Unknown89"},
@@ -202,6 +202,17 @@ public:
202 {116, nullptr, "Unknown116"}, 202 {116, nullptr, "Unknown116"},
203 {117, nullptr, "Unknown117"}, 203 {117, nullptr, "Unknown117"},
204 {118, nullptr, "Unknown118"}, 204 {118, nullptr, "Unknown118"},
205 {119, nullptr, "Unknown119"},
206 {120, nullptr, "Unknown120"},
207 {121, nullptr, "Unknown121"},
208 {122, nullptr, "Unknown122"},
209 {123, nullptr, "Unknown123"},
210 {124, nullptr, "Unknown124"},
211 {125, nullptr, "Unknown125"},
212 {126, nullptr, "Unknown126"},
213 {127, nullptr, "Unknown127"},
214 {128, nullptr, "Unknown128"},
215 {129, nullptr, "Unknown129"},
205 }; 216 };
206 // clang-format on 217 // clang-format on
207 218
diff --git a/src/core/hle/service/npns/npns.cpp b/src/core/hle/service/npns/npns.cpp
index f7a58f659..e4c703da4 100644
--- a/src/core/hle/service/npns/npns.cpp
+++ b/src/core/hle/service/npns/npns.cpp
@@ -49,6 +49,8 @@ public:
49 {151, nullptr, "GetStateWithHandover"}, 49 {151, nullptr, "GetStateWithHandover"},
50 {152, nullptr, "GetStateChangeEventWithHandover"}, 50 {152, nullptr, "GetStateChangeEventWithHandover"},
51 {153, nullptr, "GetDropEventWithHandover"}, 51 {153, nullptr, "GetDropEventWithHandover"},
52 {154, nullptr, "CreateTokenAsync"},
53 {155, nullptr, "CreateTokenAsyncWithApplicationId"},
52 {161, nullptr, "GetRequestChangeStateCancelEvent"}, 54 {161, nullptr, "GetRequestChangeStateCancelEvent"},
53 {162, nullptr, "RequestChangeStateForceTimedWithCancelEvent"}, 55 {162, nullptr, "RequestChangeStateForceTimedWithCancelEvent"},
54 {201, nullptr, "RequestChangeStateForceTimed"}, 56 {201, nullptr, "RequestChangeStateForceTimed"},
@@ -84,6 +86,7 @@ public:
84 {151, nullptr, "GetStateWithHandover"}, 86 {151, nullptr, "GetStateWithHandover"},
85 {152, nullptr, "GetStateChangeEventWithHandover"}, 87 {152, nullptr, "GetStateChangeEventWithHandover"},
86 {153, nullptr, "GetDropEventWithHandover"}, 88 {153, nullptr, "GetDropEventWithHandover"},
89 {154, nullptr, "CreateTokenAsync"},
87 }; 90 };
88 // clang-format on 91 // clang-format on
89 92
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 6ccf8995c..5fe7a9189 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -55,6 +55,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
55 {26, nullptr, "BeginInstallApplication"}, 55 {26, nullptr, "BeginInstallApplication"},
56 {27, nullptr, "DeleteApplicationRecord"}, 56 {27, nullptr, "DeleteApplicationRecord"},
57 {30, nullptr, "RequestApplicationUpdateInfo"}, 57 {30, nullptr, "RequestApplicationUpdateInfo"},
58 {31, nullptr, "Unknown31"},
58 {32, nullptr, "CancelApplicationDownload"}, 59 {32, nullptr, "CancelApplicationDownload"},
59 {33, nullptr, "ResumeApplicationDownload"}, 60 {33, nullptr, "ResumeApplicationDownload"},
60 {35, nullptr, "UpdateVersionList"}, 61 {35, nullptr, "UpdateVersionList"},
@@ -182,6 +183,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
182 {913, nullptr, "ListAllApplicationRecord"}, 183 {913, nullptr, "ListAllApplicationRecord"},
183 {914, nullptr, "HideApplicationRecord"}, 184 {914, nullptr, "HideApplicationRecord"},
184 {915, nullptr, "ShowApplicationRecord"}, 185 {915, nullptr, "ShowApplicationRecord"},
186 {916, nullptr, "IsApplicationAutoDeleteDisabled"},
185 {1000, nullptr, "RequestVerifyApplicationDeprecated"}, 187 {1000, nullptr, "RequestVerifyApplicationDeprecated"},
186 {1001, nullptr, "CorruptApplicationForDebug"}, 188 {1001, nullptr, "CorruptApplicationForDebug"},
187 {1002, nullptr, "RequestVerifyAddOnContentsRights"}, 189 {1002, nullptr, "RequestVerifyAddOnContentsRights"},
@@ -201,6 +203,8 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
201 {1310, nullptr, "RequestMoveApplicationEntity"}, 203 {1310, nullptr, "RequestMoveApplicationEntity"},
202 {1311, nullptr, "EstimateSizeToMove"}, 204 {1311, nullptr, "EstimateSizeToMove"},
203 {1312, nullptr, "HasMovableEntity"}, 205 {1312, nullptr, "HasMovableEntity"},
206 {1313, nullptr, "CleanupOrphanContents"},
207 {1314, nullptr, "CheckPreconditionSatisfiedToMove"},
204 {1400, nullptr, "PrepareShutdown"}, 208 {1400, nullptr, "PrepareShutdown"},
205 {1500, nullptr, "FormatSdCard"}, 209 {1500, nullptr, "FormatSdCard"},
206 {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, 210 {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
@@ -215,6 +219,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
215 {1702, nullptr, "GetApplicationDownloadTaskStatus"}, 219 {1702, nullptr, "GetApplicationDownloadTaskStatus"},
216 {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, 220 {1703, nullptr, "GetApplicationViewDownloadErrorContext"},
217 {1704, nullptr, "GetApplicationViewWithPromotionInfo"}, 221 {1704, nullptr, "GetApplicationViewWithPromotionInfo"},
222 {1705, nullptr, "IsPatchAutoDeletableApplication"},
218 {1800, nullptr, "IsNotificationSetupCompleted"}, 223 {1800, nullptr, "IsNotificationSetupCompleted"},
219 {1801, nullptr, "GetLastNotificationInfoCount"}, 224 {1801, nullptr, "GetLastNotificationInfoCount"},
220 {1802, nullptr, "ListLastNotificationInfo"}, 225 {1802, nullptr, "ListLastNotificationInfo"},
@@ -269,6 +274,9 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
269 {2351, nullptr, "RequestNoDownloadRightsErrorResolution"}, 274 {2351, nullptr, "RequestNoDownloadRightsErrorResolution"},
270 {2352, nullptr, "RequestResolveNoDownloadRightsError"}, 275 {2352, nullptr, "RequestResolveNoDownloadRightsError"},
271 {2353, nullptr, "GetApplicationDownloadTaskInfo"}, 276 {2353, nullptr, "GetApplicationDownloadTaskInfo"},
277 {2354, nullptr, "PrioritizeApplicationBackgroundTask"},
278 {2355, nullptr, "Unknown2355"},
279 {2356, nullptr, "Unknown2356"},
272 {2400, nullptr, "GetPromotionInfo"}, 280 {2400, nullptr, "GetPromotionInfo"},
273 {2401, nullptr, "CountPromotionInfo"}, 281 {2401, nullptr, "CountPromotionInfo"},
274 {2402, nullptr, "ListPromotionInfo"}, 282 {2402, nullptr, "ListPromotionInfo"},
@@ -282,6 +290,21 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
282 {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"}, 290 {2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"},
283 {2516, nullptr, "EnsureApplicationCertificate"}, 291 {2516, nullptr, "EnsureApplicationCertificate"},
284 {2800, nullptr, "GetApplicationIdOfPreomia"}, 292 {2800, nullptr, "GetApplicationIdOfPreomia"},
293 {3000, nullptr, "RegisterDeviceLockKey"},
294 {3001, nullptr, "UnregisterDeviceLockKey"},
295 {3002, nullptr, "VerifyDeviceLockKey"},
296 {3003, nullptr, "HideApplicationIcon"},
297 {3004, nullptr, "ShowApplicationIcon"},
298 {3005, nullptr, "HideApplicationTitle"},
299 {3006, nullptr, "ShowApplicationTitle"},
300 {3007, nullptr, "EnableGameCard"},
301 {3008, nullptr, "DisableGameCard"},
302 {3009, nullptr, "EnableLocalContentShare"},
303 {3010, nullptr, "DisableLocalContentShare"},
304 {3011, nullptr, "IsApplicationIconHidden"},
305 {3012, nullptr, "IsApplicationTitleHidden"},
306 {3013, nullptr, "IsGameCardEnabled"},
307 {3014, nullptr, "IsLocalContentShareEnabled"},
285 {9999, nullptr, "GetApplicationCertificate"}, 308 {9999, nullptr, "GetApplicationCertificate"},
286 }; 309 };
287 // clang-format on 310 // clang-format on
@@ -441,7 +464,11 @@ IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_
441 {800, nullptr, "RequestVersionList"}, 464 {800, nullptr, "RequestVersionList"},
442 {801, nullptr, "ListVersionList"}, 465 {801, nullptr, "ListVersionList"},
443 {802, nullptr, "RequestVersionListData"}, 466 {802, nullptr, "RequestVersionListData"},
467 {900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"},
468 {901, nullptr, "ListDefaultAutoUpdatePolicy"},
469 {902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"},
444 {1000, nullptr, "PerformAutoUpdate"}, 470 {1000, nullptr, "PerformAutoUpdate"},
471 {1001, nullptr, "ListAutoUpdateSchedule"},
445 }; 472 };
446 // clang-format on 473 // clang-format on
447 474
@@ -547,6 +574,9 @@ IFactoryResetInterface::~IFactoryResetInterface() = default;
547NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} { 574NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} {
548 // clang-format off 575 // clang-format off
549 static const FunctionInfo functions[] = { 576 static const FunctionInfo functions[] = {
577 {7988, nullptr, "GetDynamicRightsInterface"},
578 {7989, nullptr, "GetReadOnlyApplicationControlDataInterface"},
579 {7991, nullptr, "GetReadOnlyApplicationRecordInterface"},
550 {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, 580 {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
551 {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, 581 {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
552 {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, 582 {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"},
@@ -575,18 +605,22 @@ public:
575 {0, nullptr, "LaunchProgram"}, 605 {0, nullptr, "LaunchProgram"},
576 {1, nullptr, "TerminateProcess"}, 606 {1, nullptr, "TerminateProcess"},
577 {2, nullptr, "TerminateProgram"}, 607 {2, nullptr, "TerminateProgram"},
578 {4, nullptr, "GetShellEventHandle"}, 608 {4, nullptr, "GetShellEvent"},
579 {5, nullptr, "GetShellEventInfo"}, 609 {5, nullptr, "GetShellEventInfo"},
580 {6, nullptr, "TerminateApplication"}, 610 {6, nullptr, "TerminateApplication"},
581 {7, nullptr, "PrepareLaunchProgramFromHost"}, 611 {7, nullptr, "PrepareLaunchProgramFromHost"},
582 {8, nullptr, "LaunchApplication"}, 612 {8, nullptr, "LaunchApplicationFromHost"},
583 {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"}, 613 {9, nullptr, "LaunchApplicationWithStorageIdForDevelop"},
584 {10, nullptr, "IsSystemMemoryResourceLimitBoosted"}, 614 {10, nullptr, "IsSystemMemoryResourceLimitBoosted"},
585 {11, nullptr, "GetRunningApplicationProcessIdForDevelop"}, 615 {11, nullptr, "GetRunningApplicationProcessIdForDevelop"},
586 {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActive"}, 616 {12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"},
587 {13, nullptr, "CreateApplicationResourceForDevelop"}, 617 {13, nullptr, "CreateApplicationResourceForDevelop"},
588 {14, nullptr, "IsPreomiaForDevelop"}, 618 {14, nullptr, "IsPreomiaForDevelop"},
589 {15, nullptr, "GetApplicationProgramIdFromHost"}, 619 {15, nullptr, "GetApplicationProgramIdFromHost"},
620 {16, nullptr, "RefreshCachedDebugValues"},
621 {17, nullptr, "PrepareLaunchApplicationFromHost"},
622 {18, nullptr, "GetLaunchEvent"},
623 {19, nullptr, "GetLaunchResult"},
590 }; 624 };
591 // clang-format on 625 // clang-format on
592 626
@@ -699,6 +733,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system
699 std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager); 733 std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager);
700 std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager); 734 std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager);
701 std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager); 735 std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager);
736 std::make_shared<NS>("ns:ro", system)->InstallAsService(service_manager);
702 737
703 std::make_shared<NS_DEV>(system)->InstallAsService(service_manager); 738 std::make_shared<NS_DEV>(system)->InstallAsService(service_manager);
704 std::make_shared<NS_SU>(system)->InstallAsService(service_manager); 739 std::make_shared<NS_SU>(system)->InstallAsService(service_manager);
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index fcd15d81f..da139fdc4 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -154,6 +154,10 @@ PL_U::PL_U(Core::System& system_)
154 {100, nullptr, "RequestApplicationFunctionAuthorization"}, 154 {100, nullptr, "RequestApplicationFunctionAuthorization"},
155 {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"}, 155 {101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},
156 {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"}, 156 {102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"},
157 {103, nullptr, "RefreshApplicationFunctionBlackListDebugRecord"},
158 {104, nullptr, "RequestApplicationFunctionAuthorizationByProgramId"},
159 {105, nullptr, "GetFunctionBlackListSystemVersionToAuthorize"},
160 {106, nullptr, "GetFunctionBlackListVersion"},
157 {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"}, 161 {1000, nullptr, "LoadNgWordDataForPlatformRegionChina"},
158 {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"}, 162 {1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"},
159 }; 163 };
diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp
index e2ac71fa1..b066c3417 100644
--- a/src/core/hle/service/olsc/olsc.cpp
+++ b/src/core/hle/service/olsc/olsc.cpp
@@ -26,6 +26,7 @@ public:
26 {22, nullptr, "DeleteSaveDataBackupAsync"}, 26 {22, nullptr, "DeleteSaveDataBackupAsync"},
27 {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"}, 27 {25, nullptr, "ListDownloadableSaveDataBackupInfoAsync"},
28 {26, nullptr, "DownloadSaveDataBackupAsync"}, 28 {26, nullptr, "DownloadSaveDataBackupAsync"},
29 {27, nullptr, "UploadSaveDataBackupAsync"},
29 {9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"}, 30 {9010, nullptr, "VerifySaveDataBackupLicenseAsyncForDebug"},
30 {9013, nullptr, "GetSaveDataBackupSettingForDebug"}, 31 {9013, nullptr, "GetSaveDataBackupSettingForDebug"},
31 {9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"}, 32 {9014, nullptr, "SetSaveDataBackupSettingEnabledForDebug"},
diff --git a/src/core/hle/service/pcie/pcie.cpp b/src/core/hle/service/pcie/pcie.cpp
index f6686fc4d..9bc851591 100644
--- a/src/core/hle/service/pcie/pcie.cpp
+++ b/src/core/hle/service/pcie/pcie.cpp
@@ -37,7 +37,7 @@ public:
37 {19, nullptr, "SetIrqEnable"}, 37 {19, nullptr, "SetIrqEnable"},
38 {20, nullptr, "SetAspmEnable"}, 38 {20, nullptr, "SetAspmEnable"},
39 {21, nullptr, "SetResetUponResumeEnable"}, 39 {21, nullptr, "SetResetUponResumeEnable"},
40 {22, nullptr, "Unknown22"}, 40 {22, nullptr, "ResetFunction"},
41 {23, nullptr, "Unknown23"}, 41 {23, nullptr, "Unknown23"},
42 }; 42 };
43 // clang-format on 43 // clang-format on
diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp
index f9089bf2f..e6cd4b3c7 100644
--- a/src/core/hle/service/pctl/module.cpp
+++ b/src/core/hle/service/pctl/module.cpp
@@ -50,6 +50,7 @@ public:
50 {1046, nullptr, "DisableFeaturesForReset"}, 50 {1046, nullptr, "DisableFeaturesForReset"},
51 {1047, nullptr, "NotifyApplicationDownloadStarted"}, 51 {1047, nullptr, "NotifyApplicationDownloadStarted"},
52 {1048, nullptr, "NotifyNetworkProfileCreated"}, 52 {1048, nullptr, "NotifyNetworkProfileCreated"},
53 {1049, nullptr, "ResetFreeCommunicationApplicationList"},
53 {1061, &IParentalControlService::ConfirmStereoVisionRestrictionConfigurable, "ConfirmStereoVisionRestrictionConfigurable"}, 54 {1061, &IParentalControlService::ConfirmStereoVisionRestrictionConfigurable, "ConfirmStereoVisionRestrictionConfigurable"},
54 {1062, &IParentalControlService::GetStereoVisionRestriction, "GetStereoVisionRestriction"}, 55 {1062, &IParentalControlService::GetStereoVisionRestriction, "GetStereoVisionRestriction"},
55 {1063, &IParentalControlService::SetStereoVisionRestriction, "SetStereoVisionRestriction"}, 56 {1063, &IParentalControlService::SetStereoVisionRestriction, "SetStereoVisionRestriction"},
@@ -69,6 +70,8 @@ public:
69 {1421, nullptr, "GetAccountNickname"}, 70 {1421, nullptr, "GetAccountNickname"},
70 {1424, nullptr, "GetAccountState"}, 71 {1424, nullptr, "GetAccountState"},
71 {1425, nullptr, "RequestPostEvents"}, 72 {1425, nullptr, "RequestPostEvents"},
73 {1426, nullptr, "GetPostEventInterval"},
74 {1427, nullptr, "SetPostEventInterval"},
72 {1432, nullptr, "GetSynchronizationEvent"}, 75 {1432, nullptr, "GetSynchronizationEvent"},
73 {1451, nullptr, "StartPlayTimer"}, 76 {1451, nullptr, "StartPlayTimer"},
74 {1452, nullptr, "StopPlayTimer"}, 77 {1452, nullptr, "StopPlayTimer"},
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 1da56bc27..aec399076 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -70,6 +70,7 @@
70#include "core/hle/service/vi/vi.h" 70#include "core/hle/service/vi/vi.h"
71#include "core/hle/service/wlan/wlan.h" 71#include "core/hle/service/wlan/wlan.h"
72#include "core/reporter.h" 72#include "core/reporter.h"
73#include "core/settings.h"
73 74
74namespace Service { 75namespace Service {
75 76
@@ -146,6 +147,11 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext
146 system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, 147 system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name,
147 service_name); 148 service_name);
148 UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf)); 149 UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf));
150 if (Settings::values.use_auto_stub) {
151 LOG_WARNING(Service, "Using auto stub fallback!");
152 IPC::ResponseBuilder rb{ctx, 2};
153 rb.Push(RESULT_SUCCESS);
154 }
149} 155}
150 156
151void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { 157void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp
index b58b2c8c5..5909fdd85 100644
--- a/src/core/hle/service/set/set_sys.cpp
+++ b/src/core/hle/service/set/set_sys.cpp
@@ -261,6 +261,10 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
261 {155, nullptr, "SetAccountOnlineStorageSettings"}, 261 {155, nullptr, "SetAccountOnlineStorageSettings"},
262 {156, nullptr, "GetPctlReadyFlag"}, 262 {156, nullptr, "GetPctlReadyFlag"},
263 {157, nullptr, "SetPctlReadyFlag"}, 263 {157, nullptr, "SetPctlReadyFlag"},
264 {158, nullptr, "GetAnalogStickUserCalibrationL"},
265 {159, nullptr, "SetAnalogStickUserCalibrationL"},
266 {160, nullptr, "GetAnalogStickUserCalibrationR"},
267 {161, nullptr, "SetAnalogStickUserCalibrationR"},
264 {162, nullptr, "GetPtmBatteryVersion"}, 268 {162, nullptr, "GetPtmBatteryVersion"},
265 {163, nullptr, "SetPtmBatteryVersion"}, 269 {163, nullptr, "SetPtmBatteryVersion"},
266 {164, nullptr, "GetUsb30HostEnableFlag"}, 270 {164, nullptr, "GetUsb30HostEnableFlag"},
@@ -302,6 +306,8 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} {
302 {200, nullptr, "SetButtonConfigRegisteredSettings"}, 306 {200, nullptr, "SetButtonConfigRegisteredSettings"},
303 {201, nullptr, "GetFieldTestingFlag"}, 307 {201, nullptr, "GetFieldTestingFlag"},
304 {202, nullptr, "SetFieldTestingFlag"}, 308 {202, nullptr, "SetFieldTestingFlag"},
309 {203, nullptr, "GetPanelCrcMode"},
310 {204, nullptr, "SetPanelCrcMode"},
305 }; 311 };
306 // clang-format on 312 // clang-format on
307 313
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 2b91a89d1..94608d529 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -190,10 +190,11 @@ SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_)
190 : ServiceFramework{system_, "sm:", 4}, 190 : ServiceFramework{system_, "sm:", 4},
191 service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} { 191 service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} {
192 static const FunctionInfo functions[] = { 192 static const FunctionInfo functions[] = {
193 {0x00000000, &SM::Initialize, "Initialize"}, 193 {0, &SM::Initialize, "Initialize"},
194 {0x00000001, &SM::GetService, "GetService"}, 194 {1, &SM::GetService, "GetService"},
195 {0x00000002, &SM::RegisterService, "RegisterService"}, 195 {2, &SM::RegisterService, "RegisterService"},
196 {0x00000003, &SM::UnregisterService, "UnregisterService"}, 196 {3, &SM::UnregisterService, "UnregisterService"},
197 {4, nullptr, "DetachClient"},
197 }; 198 };
198 RegisterHandlers(functions); 199 RegisterHandlers(functions);
199} 200}
diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp
index 05681ca2d..899a64c2f 100644
--- a/src/core/hle/service/sockets/ethc.cpp
+++ b/src/core/hle/service/sockets/ethc.cpp
@@ -15,6 +15,7 @@ ETHC_C::ETHC_C(Core::System& system_) : ServiceFramework{system_, "ethc:c"} {
15 {3, nullptr, "GetMediaList"}, 15 {3, nullptr, "GetMediaList"},
16 {4, nullptr, "SetMediaType"}, 16 {4, nullptr, "SetMediaType"},
17 {5, nullptr, "GetMediaType"}, 17 {5, nullptr, "GetMediaType"},
18 {6, nullptr, "Unknown6"},
18 }; 19 };
19 // clang-format on 20 // clang-format on
20 21
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp
index 51c3739bb..1159debc5 100644
--- a/src/core/hle/service/sockets/nsd.cpp
+++ b/src/core/hle/service/sockets/nsd.cpp
@@ -9,6 +9,7 @@ namespace Service::Sockets {
9NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} { 9NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} {
10 // clang-format off 10 // clang-format off
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {5, nullptr, "GetSettingUrl"},
12 {10, nullptr, "GetSettingName"}, 13 {10, nullptr, "GetSettingName"},
13 {11, nullptr, "GetEnvironmentIdentifier"}, 14 {11, nullptr, "GetEnvironmentIdentifier"},
14 {12, nullptr, "GetDeviceId"}, 15 {12, nullptr, "GetDeviceId"},
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp
index 3a6329f56..5c71f423c 100644
--- a/src/core/hle/service/sockets/sfdnsres.cpp
+++ b/src/core/hle/service/sockets/sfdnsres.cpp
@@ -9,8 +9,8 @@ namespace Service::Sockets {
9 9
10SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"} { 10SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"} {
11 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
12 {0, nullptr, "SetDnsAddressesPrivate"}, 12 {0, nullptr, "SetDnsAddressesPrivateRequest"},
13 {1, nullptr, "GetDnsAddressPrivate"}, 13 {1, nullptr, "GetDnsAddressPrivateRequest"},
14 {2, nullptr, "GetHostByNameRequest"}, 14 {2, nullptr, "GetHostByNameRequest"},
15 {3, nullptr, "GetHostByAddrRequest"}, 15 {3, nullptr, "GetHostByAddrRequest"},
16 {4, nullptr, "GetHostStringErrorRequest"}, 16 {4, nullptr, "GetHostStringErrorRequest"},
diff --git a/src/core/hle/service/spl/spl.cpp b/src/core/hle/service/spl/spl.cpp
index 4e212610f..fff3f3c42 100644
--- a/src/core/hle/service/spl/spl.cpp
+++ b/src/core/hle/service/spl/spl.cpp
@@ -60,6 +60,8 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr<Module> module_)
60 {4, nullptr, "GenerateAesKey"}, 60 {4, nullptr, "GenerateAesKey"},
61 {5, nullptr, "SetConfig"}, 61 {5, nullptr, "SetConfig"},
62 {7, &SPL::GetRandomBytes, "GenerateRandomBytes"}, 62 {7, &SPL::GetRandomBytes, "GenerateRandomBytes"},
63 {9, nullptr, "ImportLotusKey"},
64 {10, nullptr, "DecryptLotusMessage"},
63 {11, nullptr, "IsDevelopment"}, 65 {11, nullptr, "IsDevelopment"},
64 {12, nullptr, "GenerateSpecificAesKey"}, 66 {12, nullptr, "GenerateSpecificAesKey"},
65 {14, nullptr, "DecryptAesKey"}, 67 {14, nullptr, "DecryptAesKey"},
@@ -123,6 +125,7 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr<Module> module_)
123 {14, nullptr, "DecryptAesKey"}, 125 {14, nullptr, "DecryptAesKey"},
124 {15, nullptr, "CryptAesCtr"}, 126 {15, nullptr, "CryptAesCtr"},
125 {16, nullptr, "ComputeCmac"}, 127 {16, nullptr, "ComputeCmac"},
128 {17, nullptr, "ImportEsKey"},
126 {18, nullptr, "UnwrapTitleKey"}, 129 {18, nullptr, "UnwrapTitleKey"},
127 {20, nullptr, "PrepareEsCommonKey"}, 130 {20, nullptr, "PrepareEsCommonKey"},
128 {21, nullptr, "AllocateAesKeyslot"}, 131 {21, nullptr, "AllocateAesKeyslot"},
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp
index 25cecbc83..3117627cf 100644
--- a/src/core/hle/service/time/time_zone_service.cpp
+++ b/src/core/hle/service/time/time_zone_service.cpp
@@ -20,6 +20,7 @@ ITimeZoneService ::ITimeZoneService(Core::System& system_,
20 {3, nullptr, "LoadLocationNameList"}, 20 {3, nullptr, "LoadLocationNameList"},
21 {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"}, 21 {4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
22 {5, nullptr, "GetTimeZoneRuleVersion"}, 22 {5, nullptr, "GetTimeZoneRuleVersion"},
23 {6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
23 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, 24 {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
24 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, 25 {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
25 {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"}, 26 {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp
index 579de83e4..b3b230a8c 100644
--- a/src/core/hle/service/usb/usb.cpp
+++ b/src/core/hle/service/usb/usb.cpp
@@ -69,15 +69,15 @@ public:
69 : ServiceFramework{system_, "IClientEpSession"} { 69 : ServiceFramework{system_, "IClientEpSession"} {
70 // clang-format off 70 // clang-format off
71 static const FunctionInfo functions[] = { 71 static const FunctionInfo functions[] = {
72 {0, nullptr, "Open"}, 72 {0, nullptr, "ReOpen"},
73 {1, nullptr, "Close"}, 73 {1, nullptr, "Close"},
74 {2, nullptr, "Unknown2"}, 74 {2, nullptr, "GetCompletionEvent"},
75 {3, nullptr, "Populate"}, 75 {3, nullptr, "PopulateRing"},
76 {4, nullptr, "PostBufferAsync"}, 76 {4, nullptr, "PostBufferAsync"},
77 {5, nullptr, "GetXferReport"}, 77 {5, nullptr, "GetXferReport"},
78 {6, nullptr, "PostBufferMultiAsync"}, 78 {6, nullptr, "PostBufferMultiAsync"},
79 {7, nullptr, "Unknown7"}, 79 {7, nullptr, "CreateSmmuSpace"},
80 {8, nullptr, "Unknown8"}, 80 {8, nullptr, "ShareReportRing"},
81 }; 81 };
82 // clang-format on 82 // clang-format on
83 83
@@ -91,7 +91,7 @@ public:
91 : ServiceFramework{system_, "IClientIfSession"} { 91 : ServiceFramework{system_, "IClientIfSession"} {
92 // clang-format off 92 // clang-format off
93 static const FunctionInfo functions[] = { 93 static const FunctionInfo functions[] = {
94 {0, nullptr, "Unknown0"}, 94 {0, nullptr, "GetStateChangeEvent"},
95 {1, nullptr, "SetInterface"}, 95 {1, nullptr, "SetInterface"},
96 {2, nullptr, "GetInterface"}, 96 {2, nullptr, "GetInterface"},
97 {3, nullptr, "GetAlternateInterface"}, 97 {3, nullptr, "GetAlternateInterface"},
@@ -176,15 +176,15 @@ public:
176 : ServiceFramework{system_, "IPdCradleSession"} { 176 : ServiceFramework{system_, "IPdCradleSession"} {
177 // clang-format off 177 // clang-format off
178 static const FunctionInfo functions[] = { 178 static const FunctionInfo functions[] = {
179 {0, nullptr, "VdmUserWrite"}, 179 {0, nullptr, "SetCradleVdo"},
180 {1, nullptr, "VdmUserRead"}, 180 {1, nullptr, "GetCradleVdo"},
181 {2, nullptr, "Vdm20Init"}, 181 {2, nullptr, "ResetCradleUsbHub"},
182 {3, nullptr, "GetFwType"}, 182 {3, nullptr, "GetHostPdcFirmwareType"},
183 {4, nullptr, "GetFwRevision"}, 183 {4, nullptr, "GetHostPdcFirmwareRevision"},
184 {5, nullptr, "GetManufacturerId"}, 184 {5, nullptr, "GetHostPdcManufactureId"},
185 {6, nullptr, "GetDeviceId"}, 185 {6, nullptr, "GetHostPdcDeviceId"},
186 {7, nullptr, "Unknown7"}, 186 {7, nullptr, "AwakeCradle"},
187 {8, nullptr, "Unknown8"}, 187 {8, nullptr, "SleepCradle"},
188 }; 188 };
189 // clang-format on 189 // clang-format on
190 190
@@ -219,12 +219,12 @@ public:
219 explicit USB_PM(Core::System& system_) : ServiceFramework{system_, "usb:pm"} { 219 explicit USB_PM(Core::System& system_) : ServiceFramework{system_, "usb:pm"} {
220 // clang-format off 220 // clang-format off
221 static const FunctionInfo functions[] = { 221 static const FunctionInfo functions[] = {
222 {0, nullptr, "Unknown0"}, 222 {0, nullptr, "GetPowerEvent"},
223 {1, nullptr, "Unknown1"}, 223 {1, nullptr, "GetPowerState"},
224 {2, nullptr, "Unknown2"}, 224 {2, nullptr, "GetDataEvent"},
225 {3, nullptr, "Unknown3"}, 225 {3, nullptr, "GetDataRole"},
226 {4, nullptr, "Unknown4"}, 226 {4, nullptr, "SetDiagData"},
227 {5, nullptr, "Unknown5"}, 227 {5, nullptr, "GetDiagData"},
228 }; 228 };
229 // clang-format on 229 // clang-format on
230 230
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 7423287ea..a1a7ac987 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -695,6 +695,7 @@ public:
695 {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, 695 {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"},
696 {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, 696 {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"},
697 {2209, nullptr, "SetLayerAlpha"}, 697 {2209, nullptr, "SetLayerAlpha"},
698 {2210, nullptr, "SetLayerPositionAndSize"},
698 {2312, nullptr, "CreateStrayLayer"}, 699 {2312, nullptr, "CreateStrayLayer"},
699 {2400, nullptr, "OpenIndirectLayer"}, 700 {2400, nullptr, "OpenIndirectLayer"},
700 {2401, nullptr, "CloseIndirectLayer"}, 701 {2401, nullptr, "CloseIndirectLayer"},
@@ -718,6 +719,7 @@ public:
718 {3215, nullptr, "SetDisplayGamma"}, 719 {3215, nullptr, "SetDisplayGamma"},
719 {3216, nullptr, "GetDisplayCmuLuma"}, 720 {3216, nullptr, "GetDisplayCmuLuma"},
720 {3217, nullptr, "SetDisplayCmuLuma"}, 721 {3217, nullptr, "SetDisplayCmuLuma"},
722 {3218, nullptr, "SetDisplayCrcMode"},
721 {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, 723 {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"},
722 {8225, nullptr, "GetSharedBufferMemoryHandleId"}, 724 {8225, nullptr, "GetSharedBufferMemoryHandleId"},
723 {8250, nullptr, "OpenSharedLayer"}, 725 {8250, nullptr, "OpenSharedLayer"},
@@ -729,6 +731,7 @@ public:
729 {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"}, 731 {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"},
730 {8257, nullptr, "FillSharedFrameBufferColor"}, 732 {8257, nullptr, "FillSharedFrameBufferColor"},
731 {8258, nullptr, "CancelSharedFrameBuffer"}, 733 {8258, nullptr, "CancelSharedFrameBuffer"},
734 {9000, nullptr, "GetDp2hdmiController"},
732 }; 735 };
733 RegisterHandlers(functions); 736 RegisterHandlers(functions);
734 } 737 }
@@ -808,10 +811,15 @@ public:
808 {2402, nullptr, "GetDisplayHotplugState"}, 811 {2402, nullptr, "GetDisplayHotplugState"},
809 {2501, nullptr, "GetCompositorErrorInfo"}, 812 {2501, nullptr, "GetCompositorErrorInfo"},
810 {2601, nullptr, "GetDisplayErrorEvent"}, 813 {2601, nullptr, "GetDisplayErrorEvent"},
814 {2701, nullptr, "GetDisplayFatalErrorEvent"},
811 {4201, nullptr, "SetDisplayAlpha"}, 815 {4201, nullptr, "SetDisplayAlpha"},
812 {4203, nullptr, "SetDisplayLayerStack"}, 816 {4203, nullptr, "SetDisplayLayerStack"},
813 {4205, nullptr, "SetDisplayPowerState"}, 817 {4205, nullptr, "SetDisplayPowerState"},
814 {4206, nullptr, "SetDefaultDisplay"}, 818 {4206, nullptr, "SetDefaultDisplay"},
819 {4207, nullptr, "ResetDisplayPanel"},
820 {4208, nullptr, "SetDisplayFatalErrorEnabled"},
821 {4209, nullptr, "IsDisplayPanelOn"},
822 {4300, nullptr, "GetInternalPanelId"},
815 {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, 823 {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"},
816 {6001, nullptr, "RemoveFromLayerStack"}, 824 {6001, nullptr, "RemoveFromLayerStack"},
817 {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, 825 {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"},
diff --git a/src/core/hle/service/wlan/wlan.cpp b/src/core/hle/service/wlan/wlan.cpp
index ddbf04069..44957e01d 100644
--- a/src/core/hle/service/wlan/wlan.cpp
+++ b/src/core/hle/service/wlan/wlan.cpp
@@ -46,6 +46,13 @@ public:
46 {28, nullptr, "Unknown28"}, 46 {28, nullptr, "Unknown28"},
47 {29, nullptr, "Unknown29"}, 47 {29, nullptr, "Unknown29"},
48 {30, nullptr, "Unknown30"}, 48 {30, nullptr, "Unknown30"},
49 {31, nullptr, "Unknown31"},
50 {32, nullptr, "Unknown32"},
51 {33, nullptr, "Unknown33"},
52 {34, nullptr, "Unknown34"},
53 {35, nullptr, "Unknown35"},
54 {36, nullptr, "Unknown36"},
55 {37, nullptr, "Unknown37"},
49 }; 56 };
50 // clang-format on 57 // clang-format on
51 58
diff --git a/src/core/settings.h b/src/core/settings.h
index d849dded3..a81016b23 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -222,6 +222,7 @@ struct Values {
222 bool quest_flag; 222 bool quest_flag;
223 bool disable_macro_jit; 223 bool disable_macro_jit;
224 bool extended_logging; 224 bool extended_logging;
225 bool use_auto_stub;
225 226
226 // Miscellaneous 227 // Miscellaneous
227 std::string log_filter; 228 std::string log_filter;
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index c61f44619..009c6f574 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -517,8 +517,8 @@ void GPU::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const {
517 interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value); 517 interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value);
518} 518}
519 519
520void GPU::WaitIdle() const { 520void GPU::ShutDown() {
521 gpu_thread.WaitIdle(); 521 gpu_thread.ShutDown();
522} 522}
523 523
524void GPU::OnCommandListEnd() { 524void GPU::OnCommandListEnd() {
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index b2ee45496..ecab35d3b 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -219,8 +219,8 @@ public:
219 return *shader_notify; 219 return *shader_notify;
220 } 220 }
221 221
222 // Waits for the GPU to finish working 222 // Stops the GPU execution and waits for the GPU to finish working
223 void WaitIdle() const; 223 void ShutDown();
224 224
225 /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame. 225 /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame.
226 void WaitFence(u32 syncpoint_id, u32 value); 226 void WaitFence(u32 syncpoint_id, u32 value);
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 99353f15f..7addfbc7b 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -29,8 +29,7 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
29 system.RegisterHostThread(); 29 system.RegisterHostThread();
30 30
31 // Wait for first GPU command before acquiring the window context 31 // Wait for first GPU command before acquiring the window context
32 while (state.queue.Empty()) 32 state.queue.Wait();
33 ;
34 33
35 // If emulation was stopped during disk shader loading, abort before trying to acquire context 34 // If emulation was stopped during disk shader loading, abort before trying to acquire context
36 if (!state.is_running) { 35 if (!state.is_running) {
@@ -57,11 +56,17 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
57 } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { 56 } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) {
58 rasterizer->OnCPUWrite(invalidate->addr, invalidate->size); 57 rasterizer->OnCPUWrite(invalidate->addr, invalidate->size);
59 } else if (std::holds_alternative<EndProcessingCommand>(next.data)) { 58 } else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
60 return; 59 ASSERT(state.is_running == false);
61 } else { 60 } else {
62 UNREACHABLE(); 61 UNREACHABLE();
63 } 62 }
64 state.signaled_fence.store(next.fence); 63 state.signaled_fence.store(next.fence);
64 if (next.block) {
65 // We have to lock the write_lock to ensure that the condition_variable wait not get a
66 // race between the check and the lock itself.
67 std::lock_guard lk(state.write_lock);
68 state.cv.notify_all();
69 }
65 } 70 }
66} 71}
67 72
@@ -69,13 +74,7 @@ ThreadManager::ThreadManager(Core::System& system_, bool is_async_)
69 : system{system_}, is_async{is_async_} {} 74 : system{system_}, is_async{is_async_} {}
70 75
71ThreadManager::~ThreadManager() { 76ThreadManager::~ThreadManager() {
72 if (!thread.joinable()) { 77 ShutDown();
73 return;
74 }
75
76 // Notify GPU thread that a shutdown is pending
77 PushCommand(EndProcessingCommand());
78 thread.join();
79} 78}
80 79
81void ThreadManager::StartThread(VideoCore::RendererBase& renderer, 80void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
@@ -112,9 +111,8 @@ void ThreadManager::FlushRegion(VAddr addr, u64 size) {
112 case Settings::GPUAccuracy::Extreme: { 111 case Settings::GPUAccuracy::Extreme: {
113 auto& gpu = system.GPU(); 112 auto& gpu = system.GPU();
114 u64 fence = gpu.RequestFlush(addr, size); 113 u64 fence = gpu.RequestFlush(addr, size);
115 PushCommand(GPUTickCommand()); 114 PushCommand(GPUTickCommand(), true);
116 while (fence > gpu.CurrentFlushRequestFence()) { 115 ASSERT(fence <= gpu.CurrentFlushRequestFence());
117 }
118 break; 116 break;
119 } 117 }
120 default: 118 default:
@@ -131,23 +129,45 @@ void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
131 rasterizer->OnCPUWrite(addr, size); 129 rasterizer->OnCPUWrite(addr, size);
132} 130}
133 131
134void ThreadManager::WaitIdle() const { 132void ThreadManager::ShutDown() {
135 while (state.last_fence > state.signaled_fence.load(std::memory_order_relaxed) && 133 if (!state.is_running) {
136 system.IsPoweredOn()) { 134 return;
137 } 135 }
136
137 {
138 std::lock_guard lk(state.write_lock);
139 state.is_running = false;
140 state.cv.notify_all();
141 }
142
143 if (!thread.joinable()) {
144 return;
145 }
146
147 // Notify GPU thread that a shutdown is pending
148 PushCommand(EndProcessingCommand());
149 thread.join();
138} 150}
139 151
140void ThreadManager::OnCommandListEnd() { 152void ThreadManager::OnCommandListEnd() {
141 PushCommand(OnCommandListEndCommand()); 153 PushCommand(OnCommandListEndCommand());
142} 154}
143 155
144u64 ThreadManager::PushCommand(CommandData&& command_data) { 156u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) {
145 const u64 fence{++state.last_fence};
146 state.queue.Push(CommandDataContainer(std::move(command_data), fence));
147
148 if (!is_async) { 157 if (!is_async) {
149 // In synchronous GPU mode, block the caller until the command has executed 158 // In synchronous GPU mode, block the caller until the command has executed
150 WaitIdle(); 159 block = true;
160 }
161
162 std::unique_lock lk(state.write_lock);
163 const u64 fence{++state.last_fence};
164 state.queue.Push(CommandDataContainer(std::move(command_data), fence, block));
165
166 if (block) {
167 state.cv.wait(lk, [this, fence] {
168 return fence <= state.signaled_fence.load(std::memory_order_relaxed) ||
169 !state.is_running;
170 });
151 } 171 }
152 172
153 return fence; 173 return fence;
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index 18269e51c..11a648f38 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -90,21 +90,24 @@ using CommandData =
90struct CommandDataContainer { 90struct CommandDataContainer {
91 CommandDataContainer() = default; 91 CommandDataContainer() = default;
92 92
93 explicit CommandDataContainer(CommandData&& data_, u64 next_fence_) 93 explicit CommandDataContainer(CommandData&& data_, u64 next_fence_, bool block_)
94 : data{std::move(data_)}, fence{next_fence_} {} 94 : data{std::move(data_)}, fence{next_fence_}, block(block_) {}
95 95
96 CommandData data; 96 CommandData data;
97 u64 fence{}; 97 u64 fence{};
98 bool block{};
98}; 99};
99 100
100/// Struct used to synchronize the GPU thread 101/// Struct used to synchronize the GPU thread
101struct SynchState final { 102struct SynchState final {
102 std::atomic_bool is_running{true}; 103 std::atomic_bool is_running{true};
103 104
104 using CommandQueue = Common::MPSCQueue<CommandDataContainer>; 105 using CommandQueue = Common::SPSCQueue<CommandDataContainer>;
106 std::mutex write_lock;
105 CommandQueue queue; 107 CommandQueue queue;
106 u64 last_fence{}; 108 u64 last_fence{};
107 std::atomic<u64> signaled_fence{}; 109 std::atomic<u64> signaled_fence{};
110 std::condition_variable cv;
108}; 111};
109 112
110/// Class used to manage the GPU thread 113/// Class used to manage the GPU thread
@@ -132,14 +135,14 @@ public:
132 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated 135 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
133 void FlushAndInvalidateRegion(VAddr addr, u64 size); 136 void FlushAndInvalidateRegion(VAddr addr, u64 size);
134 137
135 // Wait until the gpu thread is idle. 138 // Stops the GPU execution and waits for the GPU to finish working
136 void WaitIdle() const; 139 void ShutDown();
137 140
138 void OnCommandListEnd(); 141 void OnCommandListEnd();
139 142
140private: 143private:
141 /// Pushes a command to be executed by the GPU thread 144 /// Pushes a command to be executed by the GPU thread
142 u64 PushCommand(CommandData&& command_data); 145 u64 PushCommand(CommandData&& command_data, bool block = false);
143 146
144 Core::System& system; 147 Core::System& system;
145 const bool is_async; 148 const bool is_async;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 1bac57bb2..1d6155999 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -641,6 +641,7 @@ void Config::ReadDebuggingValues() {
641 ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool(); 641 ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool();
642 Settings::values.extended_logging = 642 Settings::values.extended_logging =
643 ReadSetting(QStringLiteral("extended_logging"), false).toBool(); 643 ReadSetting(QStringLiteral("extended_logging"), false).toBool();
644 Settings::values.use_auto_stub = ReadSetting(QStringLiteral("use_auto_stub"), false).toBool();
644 645
645 qt_config->endGroup(); 646 qt_config->endGroup();
646} 647}
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index 121873f95..2a5b3f5e7 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -34,6 +34,7 @@ void ConfigureDebug::SetConfiguration() {
34 ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args)); 34 ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args));
35 ui->reporting_services->setChecked(Settings::values.reporting_services); 35 ui->reporting_services->setChecked(Settings::values.reporting_services);
36 ui->quest_flag->setChecked(Settings::values.quest_flag); 36 ui->quest_flag->setChecked(Settings::values.quest_flag);
37 ui->use_auto_stub->setChecked(Settings::values.use_auto_stub);
37 ui->enable_graphics_debugging->setEnabled(!Core::System::GetInstance().IsPoweredOn()); 38 ui->enable_graphics_debugging->setEnabled(!Core::System::GetInstance().IsPoweredOn());
38 ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug); 39 ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug);
39 ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); 40 ui->disable_macro_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
@@ -47,6 +48,7 @@ void ConfigureDebug::ApplyConfiguration() {
47 Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); 48 Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
48 Settings::values.reporting_services = ui->reporting_services->isChecked(); 49 Settings::values.reporting_services = ui->reporting_services->isChecked();
49 Settings::values.quest_flag = ui->quest_flag->isChecked(); 50 Settings::values.quest_flag = ui->quest_flag->isChecked();
51 Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();
50 Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); 52 Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
51 Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); 53 Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
52 Settings::values.extended_logging = ui->extended_logging->isChecked(); 54 Settings::values.extended_logging = ui->extended_logging->isChecked();
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 9186aa732..ae48b728c 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -185,6 +185,28 @@
185 </property> 185 </property>
186 </widget> 186 </widget>
187 </item> 187 </item>
188 <item>
189 <widget class="QCheckBox" name="use_auto_stub">
190 <property name="text">
191 <string>Enable Auto-Stub</string>
192 </property>
193 </widget>
194 </item>
195 <item>
196 <widget class="QLabel" name="label_3">
197 <property name="font">
198 <font>
199 <italic>true</italic>
200 </font>
201 </property>
202 <property name="text">
203 <string>This will be reset automatically when yuzu closes.</string>
204 </property>
205 <property name="indent">
206 <number>20</number>
207 </property>
208 </widget>
209 </item>
188 </layout> 210 </layout>
189 </widget> 211 </widget>
190 </item> 212 </item>