summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/svc')
-rw-r--r--src/core/hle/kernel/svc/svc_exception.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_light_ipc.cpp31
-rw-r--r--src/core/hle/kernel/svc/svc_secure_monitor_call.cpp22
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp50
4 files changed, 36 insertions, 71 deletions
diff --git a/src/core/hle/kernel/svc/svc_exception.cpp b/src/core/hle/kernel/svc/svc_exception.cpp
index c581c086b..47b756828 100644
--- a/src/core/hle/kernel/svc/svc_exception.cpp
+++ b/src/core/hle/kernel/svc/svc_exception.cpp
@@ -103,9 +103,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
103 103
104 handle_debug_buffer(info1, info2); 104 handle_debug_buffer(info1, info2);
105 105
106 auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); 106 system.CurrentPhysicalCore().LogBacktrace();
107 const auto thread_processor_id = current_thread->GetActiveCore();
108 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
109 } 107 }
110 108
111 const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl(); 109 const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl();
diff --git a/src/core/hle/kernel/svc/svc_light_ipc.cpp b/src/core/hle/kernel/svc/svc_light_ipc.cpp
index b76ce984c..d757d5af2 100644
--- a/src/core/hle/kernel/svc/svc_light_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_light_ipc.cpp
@@ -37,37 +37,36 @@ Result ReplyAndReceiveLight64From32(Core::System& system, Handle session_handle,
37// Custom ABI implementation for light IPC. 37// Custom ABI implementation for light IPC.
38 38
39template <typename F> 39template <typename F>
40static void SvcWrap_LightIpc(Core::System& system, F&& cb) { 40static void SvcWrap_LightIpc(Core::System& system, std::span<uint64_t, 8> args, F&& cb) {
41 auto& core = system.CurrentArmInterface(); 41 std::array<u32, 7> ipc_args{};
42 std::array<u32, 7> arguments{};
43 42
44 Handle session_handle = static_cast<Handle>(core.GetReg(0)); 43 Handle session_handle = static_cast<Handle>(args[0]);
45 for (int i = 0; i < 7; i++) { 44 for (int i = 0; i < 7; i++) {
46 arguments[i] = static_cast<u32>(core.GetReg(i + 1)); 45 ipc_args[i] = static_cast<u32>(args[i + 1]);
47 } 46 }
48 47
49 Result ret = cb(system, session_handle, arguments.data()); 48 Result ret = cb(system, session_handle, ipc_args.data());
50 49
51 core.SetReg(0, ret.raw); 50 args[0] = ret.raw;
52 for (int i = 0; i < 7; i++) { 51 for (int i = 0; i < 7; i++) {
53 core.SetReg(i + 1, arguments[i]); 52 args[i + 1] = ipc_args[i];
54 } 53 }
55} 54}
56 55
57void SvcWrap_SendSyncRequestLight64(Core::System& system) { 56void SvcWrap_SendSyncRequestLight64(Core::System& system, std::span<uint64_t, 8> args) {
58 SvcWrap_LightIpc(system, SendSyncRequestLight64); 57 SvcWrap_LightIpc(system, args, SendSyncRequestLight64);
59} 58}
60 59
61void SvcWrap_ReplyAndReceiveLight64(Core::System& system) { 60void SvcWrap_ReplyAndReceiveLight64(Core::System& system, std::span<uint64_t, 8> args) {
62 SvcWrap_LightIpc(system, ReplyAndReceiveLight64); 61 SvcWrap_LightIpc(system, args, ReplyAndReceiveLight64);
63} 62}
64 63
65void SvcWrap_SendSyncRequestLight64From32(Core::System& system) { 64void SvcWrap_SendSyncRequestLight64From32(Core::System& system, std::span<uint64_t, 8> args) {
66 SvcWrap_LightIpc(system, SendSyncRequestLight64From32); 65 SvcWrap_LightIpc(system, args, SendSyncRequestLight64From32);
67} 66}
68 67
69void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system) { 68void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system, std::span<uint64_t, 8> args) {
70 SvcWrap_LightIpc(system, ReplyAndReceiveLight64From32); 69 SvcWrap_LightIpc(system, args, ReplyAndReceiveLight64From32);
71} 70}
72 71
73} // namespace Kernel::Svc 72} // namespace Kernel::Svc
diff --git a/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp b/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp
index 62c781551..48b564ec8 100644
--- a/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp
+++ b/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp
@@ -22,31 +22,29 @@ void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArgumen
22 22
23// Custom ABI for CallSecureMonitor. 23// Custom ABI for CallSecureMonitor.
24 24
25void SvcWrap_CallSecureMonitor64(Core::System& system) { 25void SvcWrap_CallSecureMonitor64(Core::System& system, std::span<uint64_t, 8> args) {
26 auto& core = system.CurrentPhysicalCore().ArmInterface(); 26 lp64::SecureMonitorArguments smc_args{};
27 lp64::SecureMonitorArguments args{};
28 for (int i = 0; i < 8; i++) { 27 for (int i = 0; i < 8; i++) {
29 args.r[i] = core.GetReg(i); 28 smc_args.r[i] = args[i];
30 } 29 }
31 30
32 CallSecureMonitor64(system, std::addressof(args)); 31 CallSecureMonitor64(system, std::addressof(smc_args));
33 32
34 for (int i = 0; i < 8; i++) { 33 for (int i = 0; i < 8; i++) {
35 core.SetReg(i, args.r[i]); 34 args[i] = smc_args.r[i];
36 } 35 }
37} 36}
38 37
39void SvcWrap_CallSecureMonitor64From32(Core::System& system) { 38void SvcWrap_CallSecureMonitor64From32(Core::System& system, std::span<uint64_t, 8> args) {
40 auto& core = system.CurrentPhysicalCore().ArmInterface(); 39 ilp32::SecureMonitorArguments smc_args{};
41 ilp32::SecureMonitorArguments args{};
42 for (int i = 0; i < 8; i++) { 40 for (int i = 0; i < 8; i++) {
43 args.r[i] = static_cast<u32>(core.GetReg(i)); 41 smc_args.r[i] = static_cast<u32>(args[i]);
44 } 42 }
45 43
46 CallSecureMonitor64From32(system, std::addressof(args)); 44 CallSecureMonitor64From32(system, std::addressof(smc_args));
47 45
48 for (int i = 0; i < 8; i++) { 46 for (int i = 0; i < 8; i++) {
49 core.SetReg(i, args.r[i]); 47 args[i] = smc_args.r[i];
50 } 48 }
51} 49}
52 50
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index 755fd62b5..7681afa33 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -90,8 +90,6 @@ Result StartThread(Core::System& system, Handle thread_handle) {
90 90
91/// Called when a thread exits 91/// Called when a thread exits
92void ExitThread(Core::System& system) { 92void ExitThread(Core::System& system) {
93 LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
94
95 auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); 93 auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
96 system.GlobalSchedulerContext().RemoveThread(current_thread); 94 system.GlobalSchedulerContext().RemoveThread(current_thread);
97 current_thread->Exit(); 95 current_thread->Exit();
@@ -147,47 +145,19 @@ Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_ha
147 R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); 145 R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
148 146
149 // Require the handle be to a non-current thread in the current process. 147 // Require the handle be to a non-current thread in the current process.
150 const auto* current_process = GetCurrentProcessPointer(kernel); 148 R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(kernel), ResultInvalidHandle);
151 R_UNLESS(current_process == thread->GetOwnerProcess(), ResultInvalidId); 149 R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultBusy);
152
153 // Verify that the thread isn't terminated.
154 R_UNLESS(thread->GetState() != ThreadState::Terminated, ResultTerminationRequested);
155
156 /// Check that the thread is not the current one.
157 /// NOTE: Nintendo does not check this, and thus the following loop will deadlock.
158 R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultInvalidId);
159
160 // Try to get the thread context until the thread isn't current on any core.
161 while (true) {
162 KScopedSchedulerLock sl{kernel};
163
164 // TODO(bunnei): Enforce that thread is suspended for debug here.
165
166 // If the thread's raw state isn't runnable, check if it's current on some core.
167 if (thread->GetRawState() != ThreadState::Runnable) {
168 bool current = false;
169 for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
170 if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetSchedulerCurrentThread()) {
171 current = true;
172 break;
173 }
174 }
175 150
176 // If the thread is current, retry until it isn't. 151 // Get the thread context.
177 if (current) { 152 Svc::ThreadContext context{};
178 continue; 153 R_TRY(thread->GetThreadContext3(std::addressof(context)));
179 }
180 }
181 154
182 // Get the thread context. 155 // Copy the thread context to user space.
183 static thread_local Common::ScratchBuffer<u8> context; 156 R_UNLESS(
184 R_TRY(thread->GetThreadContext3(context)); 157 GetCurrentMemory(kernel).WriteBlock(out_context, std::addressof(context), sizeof(context)),
158 ResultInvalidPointer);
185 159
186 // Copy the thread context to user space. 160 R_SUCCEED();
187 GetCurrentMemory(kernel).WriteBlock(out_context, context.data(), context.size());
188
189 R_SUCCEED();
190 }
191} 161}
192 162
193/// Gets the priority for the specified thread 163/// Gets the priority for the specified thread