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/errors.h" | ||||||
| #include "core/hle/kernel/event.h" | #include "core/hle/kernel/event.h" | ||||||
| #include "core/hle/kernel/handle_table.h" | #include "core/hle/kernel/handle_table.h" | ||||||
|  | #include "core/hle/kernel/ipc.h" | ||||||
| #include "core/hle/kernel/memory.h" | #include "core/hle/kernel/memory.h" | ||||||
| #include "core/hle/kernel/mutex.h" | #include "core/hle/kernel/mutex.h" | ||||||
| #include "core/hle/kernel/process.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.
 | /// 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, | static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count, | ||||||
|                                   Kernel::Handle reply_target) { |                                   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; |             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.
 |         // Note: The scheduler is not invoked here.
 | ||||||
|         request_thread->ResumeFromWait(); |         request_thread->ResumeFromWait(); | ||||||
|  | @ -524,14 +560,11 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_ | ||||||
|         object->Acquire(thread); |         object->Acquire(thread); | ||||||
|         *index = static_cast<s32>(std::distance(objects.begin(), itr)); |         *index = static_cast<s32>(std::distance(objects.begin(), itr)); | ||||||
| 
 | 
 | ||||||
|         if (object->GetHandleType() == Kernel::HandleType::ServerSession) { |         if (object->GetHandleType() != Kernel::HandleType::ServerSession) | ||||||
|             auto server_session = static_cast<Kernel::ServerSession*>(object); |             return RESULT_SUCCESS; | ||||||
|             if (server_session->parent->client == nullptr) |  | ||||||
|                 return Kernel::ERR_SESSION_CLOSED_BY_REMOTE; |  | ||||||
| 
 | 
 | ||||||
|             // TODO(Subv): Perform IPC translation from the ServerSession to the current thread.
 |         auto server_session = static_cast<Kernel::ServerSession*>(object); | ||||||
|         } |         return ReceiveIPCRequest(server_session, Kernel::GetCurrentThread()); | ||||||
|         return RESULT_SUCCESS; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // No objects were ready to be acquired, prepare to suspend the thread.
 |     // 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(thread->status == THREADSTATUS_WAIT_SYNCH_ANY); | ||||||
|         ASSERT(reason == ThreadWakeupReason::Signal); |         ASSERT(reason == ThreadWakeupReason::Signal); | ||||||
| 
 | 
 | ||||||
|         thread->SetWaitSynchronizationResult(RESULT_SUCCESS); |         ResultCode result = RESULT_SUCCESS; | ||||||
|         thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(object.get())); |  | ||||||
| 
 | 
 | ||||||
|         // 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(); |     Core::System::GetInstance().PrepareReschedule(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue