Просмотр исходного кода

kernel/svc: Implement svcGetThreadContext()

Now that we have all of the rearranging and proper structure sizes in
place, it's fairly trivial to implement svcGetThreadContext(). In the
64-bit case we can more or less just write out the context as is, minus
some minor value sanitizing. In the 32-bit case we'll need to clear out
the registers that wouldn't normally be accessible from a 32-bit
AArch32 exectuable (or process).
Lioncash 7 лет назад
Родитель
Сommit
541c550753
3 измененных файлов с 37 добавлено и 2 удалено
  1. 2 0
      src/core/hle/kernel/errors.h
  2. 30 2
      src/core/hle/kernel/svc.cpp
  3. 5 0
      src/core/hle/kernel/svc_wrap.h

+ 2 - 0
src/core/hle/kernel/errors.h

@@ -31,6 +31,7 @@ enum {
     TooLarge = 119,
     TooLarge = 119,
     InvalidEnumValue = 120,
     InvalidEnumValue = 120,
     NoSuchEntry = 121,
     NoSuchEntry = 121,
+    AlreadyRegistered = 122,
     InvalidState = 125,
     InvalidState = 125,
     ResourceLimitExceeded = 132,
     ResourceLimitExceeded = 132,
 };
 };
@@ -58,6 +59,7 @@ constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS(ErrorModule::Kernel,
 constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle);
 constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle);
 constexpr ResultCode ERR_INVALID_PROCESSOR_ID(ErrorModule::Kernel, ErrCodes::InvalidProcessorId);
 constexpr ResultCode ERR_INVALID_PROCESSOR_ID(ErrorModule::Kernel, ErrCodes::InvalidProcessorId);
 constexpr ResultCode ERR_INVALID_SIZE(ErrorModule::Kernel, ErrCodes::InvalidSize);
 constexpr ResultCode ERR_INVALID_SIZE(ErrorModule::Kernel, ErrCodes::InvalidSize);
+constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::Kernel, ErrCodes::AlreadyRegistered);
 constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState);
 constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState);
 constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel,
 constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel,
                                                  ErrCodes::InvalidThreadPriority);
                                                  ErrCodes::InvalidThreadPriority);

+ 30 - 2
src/core/hle/kernel/svc.cpp

@@ -415,8 +415,36 @@ static ResultCode SetThreadActivity(Handle handle, u32 unknown) {
 }
 }
 
 
 /// Gets the thread context
 /// Gets the thread context
-static ResultCode GetThreadContext(Handle handle, VAddr addr) {
-    LOG_WARNING(Kernel_SVC, "(STUBBED) called, handle=0x{:08X}, addr=0x{:X}", handle, addr);
+static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
+    LOG_DEBUG(Kernel_SVC, "called, context=0x{:08X}, thread=0x{:X}", thread_context, handle);
+
+    auto& kernel = Core::System::GetInstance().Kernel();
+    const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);
+    if (!thread) {
+        return ERR_INVALID_HANDLE;
+    }
+
+    const auto current_process = Core::CurrentProcess();
+    if (thread->owner_process != current_process) {
+        return ERR_INVALID_HANDLE;
+    }
+
+    if (thread == GetCurrentThread()) {
+        return ERR_ALREADY_REGISTERED;
+    }
+
+    Core::ARM_Interface::ThreadContext ctx = thread->context;
+    // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
+    ctx.pstate &= 0xFF0FFE20;
+
+    // If 64-bit, we can just write the context registers directly and we're good.
+    // However, if 32-bit, we have to ensure some registers are zeroed out.
+    if (!current_process->Is64BitProcess()) {
+        std::fill(ctx.cpu_registers.begin() + 15, ctx.cpu_registers.end(), 0);
+        std::fill(ctx.vector_registers.begin() + 16, ctx.vector_registers.end(), u128{});
+    }
+
+    Memory::WriteBlock(thread_context, &ctx, sizeof(ctx));
     return RESULT_SUCCESS;
     return RESULT_SUCCESS;
 }
 }
 
 

+ 5 - 0
src/core/hle/kernel/svc_wrap.h

@@ -64,6 +64,11 @@ void SvcWrap() {
     FuncReturn(func(Param(0), (s32)Param(1)).raw);
     FuncReturn(func(Param(0), (s32)Param(1)).raw);
 }
 }
 
 
+template <ResultCode func(u64, u32)>
+void SvcWrap() {
+    FuncReturn(func(Param(0), static_cast<u32>(Param(1))).raw);
+}
+
 template <ResultCode func(u64*, u64)>
 template <ResultCode func(u64*, u64)>
 void SvcWrap() {
 void SvcWrap() {
     u64 param_1 = 0;
     u64 param_1 = 0;