mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #2971 from Subv/per_process_memops
Memory: Add overloads for ReadBlock and WriteBlock that operate on a specific process.
This commit is contained in:
		
						commit
						30fabc41c6
					
				
					 4 changed files with 61 additions and 22 deletions
				
			
		|  | @ -541,6 +541,12 @@ s32 Thread::GetWaitObjectIndex(WaitObject* object) const { | ||||||
|     return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1); |     return static_cast<s32>(std::distance(match, wait_objects.rend()) - 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | VAddr Thread::GetCommandBufferAddress() const { | ||||||
|  |     // Offset from the start of TLS at which the IPC command buffer begins.
 | ||||||
|  |     static constexpr int CommandHeaderOffset = 0x80; | ||||||
|  |     return GetTLSAddress() + CommandHeaderOffset; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
| void ThreadingInit() { | void ThreadingInit() { | ||||||
|  |  | ||||||
|  | @ -164,6 +164,12 @@ public: | ||||||
|         return tls_address; |         return tls_address; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /*
 | ||||||
|  |      * Returns the address of the current thread's command buffer, located in the TLS. | ||||||
|  |      * @returns VAddr of the thread's command buffer. | ||||||
|  |      */ | ||||||
|  |     VAddr GetCommandBufferAddress() const; | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Returns whether this thread is waiting for all the objects in |      * Returns whether this thread is waiting for all the objects in | ||||||
|      * its wait list to become ready, as a result of a WaitSynchronizationN call |      * its wait list to become ready, as a result of a WaitSynchronizationN call | ||||||
|  |  | ||||||
|  | @ -82,10 +82,10 @@ void UnmapRegion(PageTable& page_table, VAddr base, u32 size) { | ||||||
|  * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned) |  * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned) | ||||||
|  * using a VMA from the current process |  * using a VMA from the current process | ||||||
|  */ |  */ | ||||||
| static u8* GetPointerFromVMA(VAddr vaddr) { | static u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) { | ||||||
|     u8* direct_pointer = nullptr; |     u8* direct_pointer = nullptr; | ||||||
| 
 | 
 | ||||||
|     auto& vm_manager = Kernel::g_current_process->vm_manager; |     auto& vm_manager = process.vm_manager; | ||||||
| 
 | 
 | ||||||
|     auto it = vm_manager.FindVMA(vaddr); |     auto it = vm_manager.FindVMA(vaddr); | ||||||
|     ASSERT(it != vm_manager.vma_map.end()); |     ASSERT(it != vm_manager.vma_map.end()); | ||||||
|  | @ -107,6 +107,14 @@ static u8* GetPointerFromVMA(VAddr vaddr) { | ||||||
|     return direct_pointer + (vaddr - vma.base); |     return direct_pointer + (vaddr - vma.base); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned) | ||||||
|  |  * using a VMA from the current process. | ||||||
|  |  */ | ||||||
|  | static u8* GetPointerFromVMA(VAddr vaddr) { | ||||||
|  |     return GetPointerFromVMA(*Kernel::g_current_process, vaddr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * This function should only be called for virtual addreses with attribute `PageType::Special`. |  * This function should only be called for virtual addreses with attribute `PageType::Special`. | ||||||
|  */ |  */ | ||||||
|  | @ -470,7 +478,10 @@ u64 Read64(const VAddr addr) { | ||||||
|     return Read<u64_le>(addr); |     return Read<u64_le>(addr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { | void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, | ||||||
|  |                const size_t size) { | ||||||
|  |     auto& page_table = process.vm_manager.page_table; | ||||||
|  | 
 | ||||||
|     size_t remaining_size = size; |     size_t remaining_size = size; | ||||||
|     size_t page_index = src_addr >> PAGE_BITS; |     size_t page_index = src_addr >> PAGE_BITS; | ||||||
|     size_t page_offset = src_addr & PAGE_MASK; |     size_t page_offset = src_addr & PAGE_MASK; | ||||||
|  | @ -479,7 +490,7 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { | ||||||
|         const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); |         const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||||||
|         const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); |         const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); | ||||||
| 
 | 
 | ||||||
|         switch (current_page_table->attributes[page_index]) { |         switch (page_table.attributes[page_index]) { | ||||||
|         case PageType::Unmapped: { |         case PageType::Unmapped: { | ||||||
|             LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", |             LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", | ||||||
|                       current_vaddr, src_addr, size); |                       current_vaddr, src_addr, size); | ||||||
|  | @ -487,29 +498,30 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case PageType::Memory: { |         case PageType::Memory: { | ||||||
|             DEBUG_ASSERT(current_page_table->pointers[page_index]); |             DEBUG_ASSERT(page_table.pointers[page_index]); | ||||||
| 
 | 
 | ||||||
|             const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; |             const u8* src_ptr = page_table.pointers[page_index] + page_offset; | ||||||
|             std::memcpy(dest_buffer, src_ptr, copy_amount); |             std::memcpy(dest_buffer, src_ptr, copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case PageType::Special: { |         case PageType::Special: { | ||||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); |             MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr); | ||||||
| 
 |             DEBUG_ASSERT(handler); | ||||||
|             GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); |             handler->ReadBlock(current_vaddr, dest_buffer, copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case PageType::RasterizerCachedMemory: { |         case PageType::RasterizerCachedMemory: { | ||||||
|             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), |             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), | ||||||
|                                          FlushMode::Flush); |                                          FlushMode::Flush); | ||||||
|             std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount); |             std::memcpy(dest_buffer, GetPointerFromVMA(process, current_vaddr), copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case PageType::RasterizerCachedSpecial: { |         case PageType::RasterizerCachedSpecial: { | ||||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); |             MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr); | ||||||
|  |             DEBUG_ASSERT(handler); | ||||||
|             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), |             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), | ||||||
|                                          FlushMode::Flush); |                                          FlushMode::Flush); | ||||||
|             GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); |             handler->ReadBlock(current_vaddr, dest_buffer, copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         default: |         default: | ||||||
|  | @ -523,6 +535,10 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { | ||||||
|  |     ReadBlock(*Kernel::g_current_process, src_addr, dest_buffer, size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Write8(const VAddr addr, const u8 data) { | void Write8(const VAddr addr, const u8 data) { | ||||||
|     Write<u8>(addr, data); |     Write<u8>(addr, data); | ||||||
| } | } | ||||||
|  | @ -539,7 +555,9 @@ void Write64(const VAddr addr, const u64 data) { | ||||||
|     Write<u64_le>(addr, data); |     Write<u64_le>(addr, data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size) { | void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, | ||||||
|  |                 const size_t size) { | ||||||
|  |     auto& page_table = process.vm_manager.page_table; | ||||||
|     size_t remaining_size = size; |     size_t remaining_size = size; | ||||||
|     size_t page_index = dest_addr >> PAGE_BITS; |     size_t page_index = dest_addr >> PAGE_BITS; | ||||||
|     size_t page_offset = dest_addr & PAGE_MASK; |     size_t page_offset = dest_addr & PAGE_MASK; | ||||||
|  | @ -548,7 +566,7 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size | ||||||
|         const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); |         const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||||||
|         const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); |         const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); | ||||||
| 
 | 
 | ||||||
|         switch (current_page_table->attributes[page_index]) { |         switch (page_table.attributes[page_index]) { | ||||||
|         case PageType::Unmapped: { |         case PageType::Unmapped: { | ||||||
|             LOG_ERROR(HW_Memory, |             LOG_ERROR(HW_Memory, | ||||||
|                       "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", |                       "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", | ||||||
|  | @ -556,29 +574,30 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case PageType::Memory: { |         case PageType::Memory: { | ||||||
|             DEBUG_ASSERT(current_page_table->pointers[page_index]); |             DEBUG_ASSERT(page_table.pointers[page_index]); | ||||||
| 
 | 
 | ||||||
|             u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; |             u8* dest_ptr = page_table.pointers[page_index] + page_offset; | ||||||
|             std::memcpy(dest_ptr, src_buffer, copy_amount); |             std::memcpy(dest_ptr, src_buffer, copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case PageType::Special: { |         case PageType::Special: { | ||||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); |             MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr); | ||||||
| 
 |             DEBUG_ASSERT(handler); | ||||||
|             GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); |             handler->WriteBlock(current_vaddr, src_buffer, copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case PageType::RasterizerCachedMemory: { |         case PageType::RasterizerCachedMemory: { | ||||||
|             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), |             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), | ||||||
|                                          FlushMode::FlushAndInvalidate); |                                          FlushMode::FlushAndInvalidate); | ||||||
|             std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); |             std::memcpy(GetPointerFromVMA(process, current_vaddr), src_buffer, copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         case PageType::RasterizerCachedSpecial: { |         case PageType::RasterizerCachedSpecial: { | ||||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); |             MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr); | ||||||
|  |             DEBUG_ASSERT(handler); | ||||||
|             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), |             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), | ||||||
|                                          FlushMode::FlushAndInvalidate); |                                          FlushMode::FlushAndInvalidate); | ||||||
|             GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); |             handler->WriteBlock(current_vaddr, src_buffer, copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         default: |         default: | ||||||
|  | @ -592,6 +611,10 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size) { | ||||||
|  |     WriteBlock(*Kernel::g_current_process, dest_addr, src_buffer, size); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void ZeroBlock(const VAddr dest_addr, const size_t size) { | void ZeroBlock(const VAddr dest_addr, const size_t size) { | ||||||
|     size_t remaining_size = size; |     size_t remaining_size = size; | ||||||
|     size_t page_index = dest_addr >> PAGE_BITS; |     size_t page_index = dest_addr >> PAGE_BITS; | ||||||
|  |  | ||||||
|  | @ -205,7 +205,11 @@ void Write16(VAddr addr, u16 data); | ||||||
| void Write32(VAddr addr, u32 data); | void Write32(VAddr addr, u32 data); | ||||||
| void Write64(VAddr addr, u64 data); | void Write64(VAddr addr, u64 data); | ||||||
| 
 | 
 | ||||||
|  | void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, | ||||||
|  |                size_t size); | ||||||
| void ReadBlock(const VAddr src_addr, void* dest_buffer, size_t size); | void ReadBlock(const VAddr src_addr, void* dest_buffer, size_t size); | ||||||
|  | void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, | ||||||
|  |                 size_t size); | ||||||
| void WriteBlock(const VAddr dest_addr, const void* src_buffer, size_t size); | void WriteBlock(const VAddr dest_addr, const void* src_buffer, size_t size); | ||||||
| void ZeroBlock(const VAddr dest_addr, const size_t size); | void ZeroBlock(const VAddr dest_addr, const size_t size); | ||||||
| void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size); | void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue