mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Kernel/SVC: Implement LLE command buffer translation in ReplyAndReceive.
The real kernel's ReplyAndReceive will retry the call until one of the objects can be acquired without causing a translation error, this is not currently implemented and the code will instead assert that the translation was a success.
This commit is contained in:
		
							parent
							
								
									8f108367c9
								
							
						
					
					
						commit
						5f92dc963c
					
				
					 1 changed files with 49 additions and 11 deletions
				
			
		|  | @ -18,6 +18,7 @@ | |||
| #include "core/hle/kernel/errors.h" | ||||
| #include "core/hle/kernel/event.h" | ||||
| #include "core/hle/kernel/handle_table.h" | ||||
| #include "core/hle/kernel/ipc.h" | ||||
| #include "core/hle/kernel/memory.h" | ||||
| #include "core/hle/kernel/mutex.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
|  | @ -453,6 +454,33 @@ static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 hand | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static ResultCode ReceiveIPCRequest(Kernel::SharedPtr<Kernel::ServerSession> server_session, | ||||
|                                     Kernel::SharedPtr<Kernel::Thread> thread) { | ||||
|     if (server_session->parent->client == nullptr) { | ||||
|         return Kernel::ERR_SESSION_CLOSED_BY_REMOTE; | ||||
|     } | ||||
| 
 | ||||
|     VAddr target_address = thread->GetCommandBufferAddress(); | ||||
|     VAddr source_address = server_session->currently_handling->GetCommandBufferAddress(); | ||||
| 
 | ||||
|     ResultCode translation_result = Kernel::TranslateCommandBuffer( | ||||
|         server_session->currently_handling, thread, source_address, target_address); | ||||
| 
 | ||||
|     // If a translation error occurred, immediately resume the client thread.
 | ||||
|     if (translation_result.IsError()) { | ||||
|         // Set the output of SendSyncRequest in the client thread to the translation output.
 | ||||
|         server_session->currently_handling->SetWaitSynchronizationResult(translation_result); | ||||
| 
 | ||||
|         server_session->currently_handling->ResumeFromWait(); | ||||
|         server_session->currently_handling = nullptr; | ||||
| 
 | ||||
|         // TODO(Subv): This path should try to wait again on the same objects.
 | ||||
|         ASSERT_MSG(false, "ReplyAndReceive translation error behavior unimplemented"); | ||||
|     } | ||||
| 
 | ||||
|     return translation_result; | ||||
| } | ||||
| 
 | ||||
| /// In a single operation, sends a IPC reply and waits for a new request.
 | ||||
| static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count, | ||||
|                                   Kernel::Handle reply_target) { | ||||
|  | @ -495,7 +523,15 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_ | |||
|             return Kernel::ERR_SESSION_CLOSED_BY_REMOTE; | ||||
|         } | ||||
| 
 | ||||
|         // TODO(Subv): Perform IPC translation from the current thread to request_thread.
 | ||||
|         VAddr source_address = Kernel::GetCurrentThread()->GetCommandBufferAddress(); | ||||
|         VAddr target_address = request_thread->GetCommandBufferAddress(); | ||||
| 
 | ||||
|         ResultCode translation_result = Kernel::TranslateCommandBuffer( | ||||
|             Kernel::GetCurrentThread(), request_thread, source_address, target_address); | ||||
| 
 | ||||
|         // Note: The real kernel seems to always panic if the Server->Client buffer translation
 | ||||
|         // fails for whatever reason.
 | ||||
|         ASSERT(translation_result.IsSuccess()); | ||||
| 
 | ||||
|         // Note: The scheduler is not invoked here.
 | ||||
|         request_thread->ResumeFromWait(); | ||||
|  | @ -524,14 +560,11 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_ | |||
|         object->Acquire(thread); | ||||
|         *index = static_cast<s32>(std::distance(objects.begin(), itr)); | ||||
| 
 | ||||
|         if (object->GetHandleType() == Kernel::HandleType::ServerSession) { | ||||
|             auto server_session = static_cast<Kernel::ServerSession*>(object); | ||||
|             if (server_session->parent->client == nullptr) | ||||
|                 return Kernel::ERR_SESSION_CLOSED_BY_REMOTE; | ||||
|         if (object->GetHandleType() != Kernel::HandleType::ServerSession) | ||||
|             return RESULT_SUCCESS; | ||||
| 
 | ||||
|             // TODO(Subv): Perform IPC translation from the ServerSession to the current thread.
 | ||||
|         } | ||||
|         return RESULT_SUCCESS; | ||||
|         auto server_session = static_cast<Kernel::ServerSession*>(object); | ||||
|         return ReceiveIPCRequest(server_session, Kernel::GetCurrentThread()); | ||||
|     } | ||||
| 
 | ||||
|     // No objects were ready to be acquired, prepare to suspend the thread.
 | ||||
|  | @ -554,10 +587,15 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_ | |||
|         ASSERT(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); | ||||
|         ASSERT(reason == ThreadWakeupReason::Signal); | ||||
| 
 | ||||
|         thread->SetWaitSynchronizationResult(RESULT_SUCCESS); | ||||
|         thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get())); | ||||
|         ResultCode result = RESULT_SUCCESS; | ||||
| 
 | ||||
|         // TODO(Subv): Perform IPC translation upon wakeup.
 | ||||
|         if (object->GetHandleType() == Kernel::HandleType::ServerSession) { | ||||
|             auto server_session = Kernel::DynamicObjectCast<Kernel::ServerSession>(object); | ||||
|             result = ReceiveIPCRequest(server_session, thread); | ||||
|         } | ||||
| 
 | ||||
|         thread->SetWaitSynchronizationResult(result); | ||||
|         thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get())); | ||||
|     }; | ||||
| 
 | ||||
|     Core::System::GetInstance().PrepareReschedule(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue