mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Merge pull request #4442 from wwylele/memory-no-kernel
Memory: decouple from Kernel
This commit is contained in:
		
						commit
						7e90abec78
					
				
					 9 changed files with 117 additions and 139 deletions
				
			
		|  | @ -409,7 +409,8 @@ static void RemoveBreakpoint(BreakpointType type, VAddr addr) { | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:08x} bytes at {:08x} of type {}", |     LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:08x} bytes at {:08x} of type {}", | ||||||
|               bp->second.len, bp->second.addr, static_cast<int>(type)); |               bp->second.len, bp->second.addr, static_cast<int>(type)); | ||||||
|     Memory::WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size()); |     Memory::WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), bp->second.addr, | ||||||
|  |                        bp->second.inst.data(), bp->second.inst.size()); | ||||||
|     Core::CPU().ClearInstructionCache(); |     Core::CPU().ClearInstructionCache(); | ||||||
|     p.erase(addr); |     p.erase(addr); | ||||||
| } | } | ||||||
|  | @ -830,12 +831,14 @@ static void ReadMemory() { | ||||||
|         SendReply("E01"); |         SendReply("E01"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!Memory::IsValidVirtualAddress(addr)) { |     if (!Memory::IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(), | ||||||
|  |                                        addr)) { | ||||||
|         return SendReply("E00"); |         return SendReply("E00"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::vector<u8> data(len); |     std::vector<u8> data(len); | ||||||
|     Memory::ReadBlock(addr, data.data(), len); |     Memory::ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, data.data(), | ||||||
|  |                       len); | ||||||
| 
 | 
 | ||||||
|     MemToGdbHex(reply, data.data(), len); |     MemToGdbHex(reply, data.data(), len); | ||||||
|     reply[len * 2] = '\0'; |     reply[len * 2] = '\0'; | ||||||
|  | @ -852,14 +855,16 @@ static void WriteMemory() { | ||||||
|     auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); |     auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); | ||||||
|     u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset)); |     u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset)); | ||||||
| 
 | 
 | ||||||
|     if (!Memory::IsValidVirtualAddress(addr)) { |     if (!Memory::IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(), | ||||||
|  |                                        addr)) { | ||||||
|         return SendReply("E00"); |         return SendReply("E00"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::vector<u8> data(len); |     std::vector<u8> data(len); | ||||||
| 
 | 
 | ||||||
|     GdbHexToMem(data.data(), len_pos + 1, len); |     GdbHexToMem(data.data(), len_pos + 1, len); | ||||||
|     Memory::WriteBlock(addr, data.data(), len); |     Memory::WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, data.data(), | ||||||
|  |                        len); | ||||||
|     Core::CPU().ClearInstructionCache(); |     Core::CPU().ClearInstructionCache(); | ||||||
|     SendReply("OK"); |     SendReply("OK"); | ||||||
| } | } | ||||||
|  | @ -912,9 +917,11 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u32 len) { | ||||||
|     breakpoint.active = true; |     breakpoint.active = true; | ||||||
|     breakpoint.addr = addr; |     breakpoint.addr = addr; | ||||||
|     breakpoint.len = len; |     breakpoint.len = len; | ||||||
|     Memory::ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size()); |     Memory::ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, | ||||||
|  |                       breakpoint.inst.data(), breakpoint.inst.size()); | ||||||
|     static constexpr std::array<u8, 4> btrap{0x70, 0x00, 0x20, 0xe1}; |     static constexpr std::array<u8, 4> btrap{0x70, 0x00, 0x20, 0xe1}; | ||||||
|     Memory::WriteBlock(addr, btrap.data(), btrap.size()); |     Memory::WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, | ||||||
|  |                        btrap.data(), btrap.size()); | ||||||
|     Core::CPU().ClearInstructionCache(); |     Core::CPU().ClearInstructionCache(); | ||||||
|     p.insert({addr, breakpoint}); |     p.insert({addr, breakpoint}); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -346,7 +346,7 @@ ResultCode SVC::UnmapMemoryBlock(Handle handle, u32 addr) { | ||||||
| 
 | 
 | ||||||
| /// Connect to an OS service given the port name, returns the handle to the port to out
 | /// Connect to an OS service given the port name, returns the handle to the port to out
 | ||||||
| ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) { | ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) { | ||||||
|     if (!Memory::IsValidVirtualAddress(port_name_address)) |     if (!Memory::IsValidVirtualAddress(*kernel.GetCurrentProcess(), port_name_address)) | ||||||
|         return ERR_NOT_FOUND; |         return ERR_NOT_FOUND; | ||||||
| 
 | 
 | ||||||
|     static constexpr std::size_t PortNameMaxLength = 11; |     static constexpr std::size_t PortNameMaxLength = 11; | ||||||
|  | @ -451,7 +451,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle | ||||||
|                                      bool wait_all, s64 nano_seconds) { |                                      bool wait_all, s64 nano_seconds) { | ||||||
|     Thread* thread = kernel.GetThreadManager().GetCurrentThread(); |     Thread* thread = kernel.GetThreadManager().GetCurrentThread(); | ||||||
| 
 | 
 | ||||||
|     if (!Memory::IsValidVirtualAddress(handles_address)) |     if (!Memory::IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) | ||||||
|         return ERR_INVALID_POINTER; |         return ERR_INVALID_POINTER; | ||||||
| 
 | 
 | ||||||
|     // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
 |     // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
 | ||||||
|  | @ -622,7 +622,7 @@ static ResultCode ReceiveIPCRequest(SharedPtr<ServerSession> server_session, | ||||||
| /// 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.
 | ||||||
| ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count, | ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count, | ||||||
|                                 Handle reply_target) { |                                 Handle reply_target) { | ||||||
|     if (!Memory::IsValidVirtualAddress(handles_address)) |     if (!Memory::IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) | ||||||
|         return ERR_INVALID_POINTER; |         return ERR_INVALID_POINTER; | ||||||
| 
 | 
 | ||||||
|     // Check if 'handle_count' is invalid
 |     // Check if 'handle_count' is invalid
 | ||||||
|  | @ -801,7 +801,7 @@ void SVC::OutputDebugString(VAddr address, s32 len) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::string string(len, ' '); |     std::string string(len, ' '); | ||||||
|     Memory::ReadBlock(address, string.data(), len); |     Memory::ReadBlock(*kernel.GetCurrentProcess(), address, string.data(), len); | ||||||
|     LOG_DEBUG(Debug_Emulated, "{}", string); |     LOG_DEBUG(Debug_Emulated, "{}", string); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -502,7 +502,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | ||||||
| 
 | 
 | ||||||
|         // TODO(Subv): These memory accesses should not go through the application's memory mapping.
 |         // TODO(Subv): These memory accesses should not go through the application's memory mapping.
 | ||||||
|         // They should go through the GSP module's memory mapping.
 |         // They should go through the GSP module's memory mapping.
 | ||||||
|         Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, |         Memory::CopyBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), | ||||||
|  |                           command.dma_request.dest_address, command.dma_request.source_address, | ||||||
|                           command.dma_request.size); |                           command.dma_request.size); | ||||||
|         SignalInterrupt(InterruptId::DMA); |         SignalInterrupt(InterruptId::DMA); | ||||||
|         break; |         break; | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| #include "common/scope_exit.h" | #include "common/scope_exit.h" | ||||||
| #include "core/arm/arm_interface.h" | #include "core/arm/arm_interface.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
| #include "core/hle/service/ldr_ro/cro_helper.h" | #include "core/hle/service/ldr_ro/cro_helper.h" | ||||||
| 
 | 
 | ||||||
| namespace Service::LDR { | namespace Service::LDR { | ||||||
|  | @ -120,7 +121,7 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool | ||||||
|     VAddr relocation_address = batch; |     VAddr relocation_address = batch; | ||||||
|     while (true) { |     while (true) { | ||||||
|         RelocationEntry relocation; |         RelocationEntry relocation; | ||||||
|         Memory::ReadBlock(relocation_address, &relocation, sizeof(RelocationEntry)); |         Memory::ReadBlock(process, relocation_address, &relocation, sizeof(RelocationEntry)); | ||||||
| 
 | 
 | ||||||
|         VAddr relocation_target = SegmentTagToAddress(relocation.target_position); |         VAddr relocation_target = SegmentTagToAddress(relocation.target_position); | ||||||
|         if (relocation_target == 0) { |         if (relocation_target == 0) { | ||||||
|  | @ -141,9 +142,9 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     RelocationEntry relocation; |     RelocationEntry relocation; | ||||||
|     Memory::ReadBlock(batch, &relocation, sizeof(RelocationEntry)); |     Memory::ReadBlock(process, batch, &relocation, sizeof(RelocationEntry)); | ||||||
|     relocation.is_batch_resolved = reset ? 0 : 1; |     relocation.is_batch_resolved = reset ? 0 : 1; | ||||||
|     Memory::WriteBlock(batch, &relocation, sizeof(RelocationEntry)); |     Memory::WriteBlock(process, batch, &relocation, sizeof(RelocationEntry)); | ||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -547,7 +548,7 @@ ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { | ||||||
|         static_relocation_table_offset + |         static_relocation_table_offset + | ||||||
|         GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); |         GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); | ||||||
| 
 | 
 | ||||||
|     CROHelper crs(crs_address); |     CROHelper crs(crs_address, process); | ||||||
|     u32 offset_export_num = GetField(StaticAnonymousSymbolNum); |     u32 offset_export_num = GetField(StaticAnonymousSymbolNum); | ||||||
|     LOG_INFO(Service_LDR, "CRO \"{}\" exports {} static anonymous symbols", ModuleName(), |     LOG_INFO(Service_LDR, "CRO \"{}\" exports {} static anonymous symbols", ModuleName(), | ||||||
|              offset_export_num); |              offset_export_num); | ||||||
|  | @ -753,11 +754,12 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) { | ||||||
|         GetEntry(i, entry); |         GetEntry(i, entry); | ||||||
|         VAddr relocation_addr = entry.relocation_batch_offset; |         VAddr relocation_addr = entry.relocation_batch_offset; | ||||||
|         ExternalRelocationEntry relocation_entry; |         ExternalRelocationEntry relocation_entry; | ||||||
|         Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |         Memory::ReadBlock(process, relocation_addr, &relocation_entry, | ||||||
|  |                           sizeof(ExternalRelocationEntry)); | ||||||
| 
 | 
 | ||||||
|         if (!relocation_entry.is_batch_resolved) { |         if (!relocation_entry.is_batch_resolved) { | ||||||
|             ResultCode result = |             ResultCode result = | ||||||
|                 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { |                 ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal<bool> { | ||||||
|                     std::string symbol_name = |                     std::string symbol_name = | ||||||
|                         Memory::ReadCString(entry.name_offset, import_strings_size); |                         Memory::ReadCString(entry.name_offset, import_strings_size); | ||||||
|                     u32 symbol_address = source.FindExportNamedSymbol(symbol_name); |                     u32 symbol_address = source.FindExportNamedSymbol(symbol_name); | ||||||
|  | @ -795,7 +797,8 @@ ResultCode CROHelper::ResetImportNamedSymbol() { | ||||||
|         GetEntry(i, entry); |         GetEntry(i, entry); | ||||||
|         VAddr relocation_addr = entry.relocation_batch_offset; |         VAddr relocation_addr = entry.relocation_batch_offset; | ||||||
|         ExternalRelocationEntry relocation_entry; |         ExternalRelocationEntry relocation_entry; | ||||||
|         Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |         Memory::ReadBlock(process, relocation_addr, &relocation_entry, | ||||||
|  |                           sizeof(ExternalRelocationEntry)); | ||||||
| 
 | 
 | ||||||
|         ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); |         ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); | ||||||
|         if (result.IsError()) { |         if (result.IsError()) { | ||||||
|  | @ -815,7 +818,8 @@ ResultCode CROHelper::ResetImportIndexedSymbol() { | ||||||
|         GetEntry(i, entry); |         GetEntry(i, entry); | ||||||
|         VAddr relocation_addr = entry.relocation_batch_offset; |         VAddr relocation_addr = entry.relocation_batch_offset; | ||||||
|         ExternalRelocationEntry relocation_entry; |         ExternalRelocationEntry relocation_entry; | ||||||
|         Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |         Memory::ReadBlock(process, relocation_addr, &relocation_entry, | ||||||
|  |                           sizeof(ExternalRelocationEntry)); | ||||||
| 
 | 
 | ||||||
|         ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); |         ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); | ||||||
|         if (result.IsError()) { |         if (result.IsError()) { | ||||||
|  | @ -835,7 +839,8 @@ ResultCode CROHelper::ResetImportAnonymousSymbol() { | ||||||
|         GetEntry(i, entry); |         GetEntry(i, entry); | ||||||
|         VAddr relocation_addr = entry.relocation_batch_offset; |         VAddr relocation_addr = entry.relocation_batch_offset; | ||||||
|         ExternalRelocationEntry relocation_entry; |         ExternalRelocationEntry relocation_entry; | ||||||
|         Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |         Memory::ReadBlock(process, relocation_addr, &relocation_entry, | ||||||
|  |                           sizeof(ExternalRelocationEntry)); | ||||||
| 
 | 
 | ||||||
|         ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); |         ResultCode result = ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); | ||||||
|         if (result.IsError()) { |         if (result.IsError()) { | ||||||
|  | @ -856,13 +861,13 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { | ||||||
|         std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); |         std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); | ||||||
| 
 | 
 | ||||||
|         ResultCode result = |         ResultCode result = | ||||||
|             ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { |             ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal<bool> { | ||||||
|                 if (want_cro_name == source.ModuleName()) { |                 if (want_cro_name == source.ModuleName()) { | ||||||
|                     LOG_INFO(Service_LDR, "CRO \"{}\" imports {} indexed symbols from \"{}\"", |                     LOG_INFO(Service_LDR, "CRO \"{}\" imports {} indexed symbols from \"{}\"", | ||||||
|                              ModuleName(), entry.import_indexed_symbol_num, source.ModuleName()); |                              ModuleName(), entry.import_indexed_symbol_num, source.ModuleName()); | ||||||
|                     for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { |                     for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { | ||||||
|                         ImportIndexedSymbolEntry im; |                         ImportIndexedSymbolEntry im; | ||||||
|                         entry.GetImportIndexedSymbolEntry(j, im); |                         entry.GetImportIndexedSymbolEntry(process, j, im); | ||||||
|                         ExportIndexedSymbolEntry ex; |                         ExportIndexedSymbolEntry ex; | ||||||
|                         source.GetEntry(im.index, ex); |                         source.GetEntry(im.index, ex); | ||||||
|                         u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); |                         u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); | ||||||
|  | @ -879,7 +884,7 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) { | ||||||
|                              ModuleName(), entry.import_anonymous_symbol_num, source.ModuleName()); |                              ModuleName(), entry.import_anonymous_symbol_num, source.ModuleName()); | ||||||
|                     for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { |                     for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { | ||||||
|                         ImportAnonymousSymbolEntry im; |                         ImportAnonymousSymbolEntry im; | ||||||
|                         entry.GetImportAnonymousSymbolEntry(j, im); |                         entry.GetImportAnonymousSymbolEntry(process, j, im); | ||||||
|                         u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); |                         u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); | ||||||
|                         LOG_TRACE(Service_LDR, "    Imports 0x{:08X}", symbol_address); |                         LOG_TRACE(Service_LDR, "    Imports 0x{:08X}", symbol_address); | ||||||
|                         ResultCode result = |                         ResultCode result = | ||||||
|  | @ -911,7 +916,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { | ||||||
|         target.GetEntry(i, entry); |         target.GetEntry(i, entry); | ||||||
|         VAddr relocation_addr = entry.relocation_batch_offset; |         VAddr relocation_addr = entry.relocation_batch_offset; | ||||||
|         ExternalRelocationEntry relocation_entry; |         ExternalRelocationEntry relocation_entry; | ||||||
|         Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |         Memory::ReadBlock(process, relocation_addr, &relocation_entry, | ||||||
|  |                           sizeof(ExternalRelocationEntry)); | ||||||
| 
 | 
 | ||||||
|         if (!relocation_entry.is_batch_resolved) { |         if (!relocation_entry.is_batch_resolved) { | ||||||
|             std::string symbol_name = |             std::string symbol_name = | ||||||
|  | @ -941,7 +947,8 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { | ||||||
|         target.GetEntry(i, entry); |         target.GetEntry(i, entry); | ||||||
|         VAddr relocation_addr = entry.relocation_batch_offset; |         VAddr relocation_addr = entry.relocation_batch_offset; | ||||||
|         ExternalRelocationEntry relocation_entry; |         ExternalRelocationEntry relocation_entry; | ||||||
|         Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |         Memory::ReadBlock(process, relocation_addr, &relocation_entry, | ||||||
|  |                           sizeof(ExternalRelocationEntry)); | ||||||
| 
 | 
 | ||||||
|         if (relocation_entry.is_batch_resolved) { |         if (relocation_entry.is_batch_resolved) { | ||||||
|             std::string symbol_name = |             std::string symbol_name = | ||||||
|  | @ -976,7 +983,7 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) { | ||||||
|                  entry.import_indexed_symbol_num, target.ModuleName()); |                  entry.import_indexed_symbol_num, target.ModuleName()); | ||||||
|         for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { |         for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { | ||||||
|             ImportIndexedSymbolEntry im; |             ImportIndexedSymbolEntry im; | ||||||
|             entry.GetImportIndexedSymbolEntry(j, im); |             entry.GetImportIndexedSymbolEntry(process, j, im); | ||||||
|             ExportIndexedSymbolEntry ex; |             ExportIndexedSymbolEntry ex; | ||||||
|             GetEntry(im.index, ex); |             GetEntry(im.index, ex); | ||||||
|             u32 symbol_address = SegmentTagToAddress(ex.symbol_position); |             u32 symbol_address = SegmentTagToAddress(ex.symbol_position); | ||||||
|  | @ -993,7 +1000,7 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) { | ||||||
|                  entry.import_anonymous_symbol_num, target.ModuleName()); |                  entry.import_anonymous_symbol_num, target.ModuleName()); | ||||||
|         for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { |         for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { | ||||||
|             ImportAnonymousSymbolEntry im; |             ImportAnonymousSymbolEntry im; | ||||||
|             entry.GetImportAnonymousSymbolEntry(j, im); |             entry.GetImportAnonymousSymbolEntry(process, j, im); | ||||||
|             u32 symbol_address = SegmentTagToAddress(im.symbol_position); |             u32 symbol_address = SegmentTagToAddress(im.symbol_position); | ||||||
|             LOG_TRACE(Service_LDR, "    exports symbol 0x{:08X}", symbol_address); |             LOG_TRACE(Service_LDR, "    exports symbol 0x{:08X}", symbol_address); | ||||||
|             ResultCode result = |             ResultCode result = | ||||||
|  | @ -1025,7 +1032,7 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) { | ||||||
|                   target.ModuleName()); |                   target.ModuleName()); | ||||||
|         for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { |         for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { | ||||||
|             ImportIndexedSymbolEntry im; |             ImportIndexedSymbolEntry im; | ||||||
|             entry.GetImportIndexedSymbolEntry(j, im); |             entry.GetImportIndexedSymbolEntry(process, j, im); | ||||||
|             ResultCode result = |             ResultCode result = | ||||||
|                 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); |                 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); | ||||||
|             if (result.IsError()) { |             if (result.IsError()) { | ||||||
|  | @ -1038,7 +1045,7 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) { | ||||||
|                   target.ModuleName()); |                   target.ModuleName()); | ||||||
|         for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { |         for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { | ||||||
|             ImportAnonymousSymbolEntry im; |             ImportAnonymousSymbolEntry im; | ||||||
|             entry.GetImportAnonymousSymbolEntry(j, im); |             entry.GetImportAnonymousSymbolEntry(process, j, im); | ||||||
|             ResultCode result = |             ResultCode result = | ||||||
|                 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); |                 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); | ||||||
|             if (result.IsError()) { |             if (result.IsError()) { | ||||||
|  | @ -1059,11 +1066,12 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) { | ||||||
|         GetEntry(i, entry); |         GetEntry(i, entry); | ||||||
|         VAddr relocation_addr = entry.relocation_batch_offset; |         VAddr relocation_addr = entry.relocation_batch_offset; | ||||||
|         ExternalRelocationEntry relocation_entry; |         ExternalRelocationEntry relocation_entry; | ||||||
|         Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); |         Memory::ReadBlock(process, relocation_addr, &relocation_entry, | ||||||
|  |                           sizeof(ExternalRelocationEntry)); | ||||||
| 
 | 
 | ||||||
|         if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") { |         if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") { | ||||||
|             ResultCode result = |             ResultCode result = | ||||||
|                 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { |                 ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal<bool> { | ||||||
|                     u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); |                     u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); | ||||||
| 
 | 
 | ||||||
|                     if (symbol_address != 0) { |                     if (symbol_address != 0) { | ||||||
|  | @ -1291,7 +1299,7 @@ ResultCode CROHelper::Link(VAddr crs_address, bool link_on_load_bug_fix) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Exports symbols to other modules
 |     // Exports symbols to other modules
 | ||||||
|     result = ForEachAutoLinkCRO(crs_address, [this](CROHelper target) -> ResultVal<bool> { |     result = ForEachAutoLinkCRO(process, crs_address, [this](CROHelper target) -> ResultVal<bool> { | ||||||
|         ResultCode result = ApplyExportNamedSymbol(target); |         ResultCode result = ApplyExportNamedSymbol(target); | ||||||
|         if (result.IsError()) |         if (result.IsError()) | ||||||
|             return result; |             return result; | ||||||
|  | @ -1335,7 +1343,7 @@ ResultCode CROHelper::Unlink(VAddr crs_address) { | ||||||
| 
 | 
 | ||||||
|     // Resets all symbols in other modules imported from this module
 |     // Resets all symbols in other modules imported from this module
 | ||||||
|     // Note: the RO service seems only searching in auto-link modules
 |     // Note: the RO service seems only searching in auto-link modules
 | ||||||
|     result = ForEachAutoLinkCRO(crs_address, [this](CROHelper target) -> ResultVal<bool> { |     result = ForEachAutoLinkCRO(process, crs_address, [this](CROHelper target) -> ResultVal<bool> { | ||||||
|         ResultCode result = ResetExportNamedSymbol(target); |         ResultCode result = ResetExportNamedSymbol(target); | ||||||
|         if (result.IsError()) |         if (result.IsError()) | ||||||
|             return result; |             return result; | ||||||
|  | @ -1375,13 +1383,13 @@ void CROHelper::InitCRS() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CROHelper::Register(VAddr crs_address, bool auto_link) { | void CROHelper::Register(VAddr crs_address, bool auto_link) { | ||||||
|     CROHelper crs(crs_address); |     CROHelper crs(crs_address, process); | ||||||
|     CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule()); |     CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule(), process); | ||||||
| 
 | 
 | ||||||
|     if (head.module_address) { |     if (head.module_address) { | ||||||
|         // there are already CROs registered
 |         // there are already CROs registered
 | ||||||
|         // register as the new tail
 |         // register as the new tail
 | ||||||
|         CROHelper tail(head.PreviousModule()); |         CROHelper tail(head.PreviousModule(), process); | ||||||
| 
 | 
 | ||||||
|         // link with the old tail
 |         // link with the old tail
 | ||||||
|         ASSERT(tail.NextModule() == 0); |         ASSERT(tail.NextModule() == 0); | ||||||
|  | @ -1407,9 +1415,9 @@ void CROHelper::Register(VAddr crs_address, bool auto_link) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CROHelper::Unregister(VAddr crs_address) { | void CROHelper::Unregister(VAddr crs_address) { | ||||||
|     CROHelper crs(crs_address); |     CROHelper crs(crs_address, process); | ||||||
|     CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule()); |     CROHelper next_head(crs.NextModule(), process), previous_head(crs.PreviousModule(), process); | ||||||
|     CROHelper next(NextModule()), previous(PreviousModule()); |     CROHelper next(NextModule(), process), previous(PreviousModule(), process); | ||||||
| 
 | 
 | ||||||
|     if (module_address == next_head.module_address || |     if (module_address == next_head.module_address || | ||||||
|         module_address == previous_head.module_address) { |         module_address == previous_head.module_address) { | ||||||
|  |  | ||||||
|  | @ -11,6 +11,10 @@ | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| 
 | 
 | ||||||
|  | namespace Kernel { | ||||||
|  | class Process; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| namespace Service::LDR { | namespace Service::LDR { | ||||||
| 
 | 
 | ||||||
| // GCC versions < 5.0 do not implement std::is_trivially_copyable.
 | // GCC versions < 5.0 do not implement std::is_trivially_copyable.
 | ||||||
|  | @ -36,7 +40,8 @@ static constexpr u32 CRO_HASH_SIZE = 0x80; | ||||||
| class CROHelper final { | class CROHelper final { | ||||||
| public: | public: | ||||||
|     // TODO (wwylele): pass in the process handle for memory access
 |     // TODO (wwylele): pass in the process handle for memory access
 | ||||||
|     explicit CROHelper(VAddr cro_address) : module_address(cro_address) {} |     explicit CROHelper(VAddr cro_address, Kernel::Process& process) | ||||||
|  |         : module_address(cro_address), process(process) {} | ||||||
| 
 | 
 | ||||||
|     std::string ModuleName() const { |     std::string ModuleName() const { | ||||||
|         return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize)); |         return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize)); | ||||||
|  | @ -144,6 +149,7 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     const VAddr module_address; ///< the virtual address of this module
 |     const VAddr module_address; ///< the virtual address of this module
 | ||||||
|  |     Kernel::Process& process;   ///< the owner process of this module
 | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Each item in this enum represents a u32 field in the header begin from address+0x80, |      * Each item in this enum represents a u32 field in the header begin from address+0x80, | ||||||
|  | @ -311,14 +317,18 @@ private: | ||||||
| 
 | 
 | ||||||
|         static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; |         static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; | ||||||
| 
 | 
 | ||||||
|         void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) { |         void GetImportIndexedSymbolEntry(Kernel::Process& process, u32 index, | ||||||
|             Memory::ReadBlock(import_indexed_symbol_table_offset + |                                          ImportIndexedSymbolEntry& entry) { | ||||||
|  |             Memory::ReadBlock(process, | ||||||
|  |                               import_indexed_symbol_table_offset + | ||||||
|                                   index * sizeof(ImportIndexedSymbolEntry), |                                   index * sizeof(ImportIndexedSymbolEntry), | ||||||
|                               &entry, sizeof(ImportIndexedSymbolEntry)); |                               &entry, sizeof(ImportIndexedSymbolEntry)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) { |         void GetImportAnonymousSymbolEntry(Kernel::Process& process, u32 index, | ||||||
|             Memory::ReadBlock(import_anonymous_symbol_table_offset + |                                            ImportAnonymousSymbolEntry& entry) { | ||||||
|  |             Memory::ReadBlock(process, | ||||||
|  |                               import_anonymous_symbol_table_offset + | ||||||
|                                   index * sizeof(ImportAnonymousSymbolEntry), |                                   index * sizeof(ImportAnonymousSymbolEntry), | ||||||
|                               &entry, sizeof(ImportAnonymousSymbolEntry)); |                               &entry, sizeof(ImportAnonymousSymbolEntry)); | ||||||
|         } |         } | ||||||
|  | @ -413,7 +423,8 @@ private: | ||||||
|      */ |      */ | ||||||
|     template <typename T> |     template <typename T> | ||||||
|     void GetEntry(std::size_t index, T& data) const { |     void GetEntry(std::size_t index, T& data) const { | ||||||
|         Memory::ReadBlock(GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)), |         Memory::ReadBlock(process, | ||||||
|  |                           GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)), | ||||||
|                           &data, sizeof(T)); |                           &data, sizeof(T)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -426,7 +437,8 @@ private: | ||||||
|      */ |      */ | ||||||
|     template <typename T> |     template <typename T> | ||||||
|     void SetEntry(std::size_t index, const T& data) { |     void SetEntry(std::size_t index, const T& data) { | ||||||
|         Memory::WriteBlock(GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)), |         Memory::WriteBlock(process, | ||||||
|  |                            GetField(T::TABLE_OFFSET_FIELD) + static_cast<u32>(index * sizeof(T)), | ||||||
|                            &data, sizeof(T)); |                            &data, sizeof(T)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -466,10 +478,11 @@ private: | ||||||
|      *         otherwise error code of the last iteration. |      *         otherwise error code of the last iteration. | ||||||
|      */ |      */ | ||||||
|     template <typename FunctionObject> |     template <typename FunctionObject> | ||||||
|     static ResultCode ForEachAutoLinkCRO(VAddr crs_address, FunctionObject func) { |     static ResultCode ForEachAutoLinkCRO(Kernel::Process& process, VAddr crs_address, | ||||||
|  |                                          FunctionObject func) { | ||||||
|         VAddr current = crs_address; |         VAddr current = crs_address; | ||||||
|         while (current != 0) { |         while (current != 0) { | ||||||
|             CROHelper cro(current); |             CROHelper cro(current, process); | ||||||
|             CASCADE_RESULT(bool next, func(cro)); |             CASCADE_RESULT(bool next, func(cro)); | ||||||
|             if (!next) |             if (!next) | ||||||
|                 break; |                 break; | ||||||
|  |  | ||||||
|  | @ -115,7 +115,7 @@ void RO::Initialize(Kernel::HLERequestContext& ctx) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     CROHelper crs(crs_address); |     CROHelper crs(crs_address, *process); | ||||||
|     crs.InitCRS(); |     crs.InitCRS(); | ||||||
| 
 | 
 | ||||||
|     result = crs.Rebase(0, crs_size, 0, 0, 0, 0, true); |     result = crs.Rebase(0, crs_size, 0, 0, 0, 0, true); | ||||||
|  | @ -249,7 +249,7 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     CROHelper cro(cro_address); |     CROHelper cro(cro_address, *process); | ||||||
| 
 | 
 | ||||||
|     result = cro.VerifyHash(cro_size, crr_address); |     result = cro.VerifyHash(cro_size, crr_address); | ||||||
|     if (result.IsError()) { |     if (result.IsError()) { | ||||||
|  | @ -331,7 +331,7 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) { | ||||||
|     LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}, zero={}, cro_buffer_ptr=0x{:08X}", |     LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}, zero={}, cro_buffer_ptr=0x{:08X}", | ||||||
|               cro_address, zero, cro_buffer_ptr); |               cro_address, zero, cro_buffer_ptr); | ||||||
| 
 | 
 | ||||||
|     CROHelper cro(cro_address); |     CROHelper cro(cro_address, *process); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
| 
 | 
 | ||||||
|  | @ -398,7 +398,7 @@ void RO::LinkCRO(Kernel::HLERequestContext& ctx) { | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address); |     LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address); | ||||||
| 
 | 
 | ||||||
|     CROHelper cro(cro_address); |     CROHelper cro(cro_address, *process); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
| 
 | 
 | ||||||
|  | @ -438,7 +438,7 @@ void RO::UnlinkCRO(Kernel::HLERequestContext& ctx) { | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address); |     LOG_DEBUG(Service_LDR, "called, cro_address=0x{:08X}", cro_address); | ||||||
| 
 | 
 | ||||||
|     CROHelper cro(cro_address); |     CROHelper cro(cro_address, *process); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
| 
 | 
 | ||||||
|  | @ -487,7 +487,7 @@ void RO::Shutdown(Kernel::HLERequestContext& ctx) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     CROHelper crs(slot->loaded_crs); |     CROHelper crs(slot->loaded_crs, *process); | ||||||
|     crs.Unrebase(true); |     crs.Unrebase(true); | ||||||
| 
 | 
 | ||||||
|     ResultCode result = RESULT_SUCCESS; |     ResultCode result = RESULT_SUCCESS; | ||||||
|  |  | ||||||
|  | @ -79,39 +79,24 @@ 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 the pointer for virtual memory where the page is marked as RasterizerCachedMemory. | ||||||
|  * using a VMA from the current process |  * This is used to access the memory where the page pointer is nullptr due to rasterizer cache. | ||||||
|  |  * Since the cache only happens on linear heap or VRAM, we know the exact physical address and | ||||||
|  |  * pointer of such virtual address | ||||||
|  */ |  */ | ||||||
| static u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) { | static u8* GetPointerForRasterizerCache(VAddr addr) { | ||||||
|     u8* direct_pointer = nullptr; |     if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { | ||||||
| 
 |         return fcram.data() + (addr - LINEAR_HEAP_VADDR); | ||||||
|     auto& vm_manager = process.vm_manager; |     } | ||||||
| 
 |     if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { | ||||||
|     auto it = vm_manager.FindVMA(vaddr); |         return fcram.data() + (addr - NEW_LINEAR_HEAP_VADDR); | ||||||
|     ASSERT(it != vm_manager.vma_map.end()); |     } | ||||||
| 
 |     if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { | ||||||
|     auto& vma = it->second; |         return vram.data() + (addr - VRAM_VADDR); | ||||||
|     switch (vma.type) { |     } | ||||||
|     case Kernel::VMAType::BackingMemory: |  | ||||||
|         direct_pointer = vma.backing_memory; |  | ||||||
|         break; |  | ||||||
|     case Kernel::VMAType::Free: |  | ||||||
|         return nullptr; |  | ||||||
|     default: |  | ||||||
|     UNREACHABLE(); |     UNREACHABLE(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|     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(*Core::System::GetInstance().Kernel().GetCurrentProcess(), 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`. | ||||||
|  */ |  */ | ||||||
|  | @ -125,12 +110,6 @@ static MMIORegionPointer GetMMIOHandler(const PageTable& page_table, VAddr vaddr | ||||||
|     return nullptr; // Should never happen
 |     return nullptr; // Should never happen
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static MMIORegionPointer GetMMIOHandler(VAddr vaddr) { |  | ||||||
|     const PageTable& page_table = |  | ||||||
|         Core::System::GetInstance().Kernel().GetCurrentProcess()->vm_manager.page_table; |  | ||||||
|     return GetMMIOHandler(page_table, vaddr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <typename T> | template <typename T> | ||||||
| T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); | T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); | ||||||
| 
 | 
 | ||||||
|  | @ -159,11 +138,11 @@ T Read(const VAddr vaddr) { | ||||||
|         RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush); |         RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush); | ||||||
| 
 | 
 | ||||||
|         T value; |         T value; | ||||||
|         std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T)); |         std::memcpy(&value, GetPointerForRasterizerCache(vaddr), sizeof(T)); | ||||||
|         return value; |         return value; | ||||||
|     } |     } | ||||||
|     case PageType::Special: |     case PageType::Special: | ||||||
|         return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); |         return ReadMMIO<T>(GetMMIOHandler(*current_page_table, vaddr), vaddr); | ||||||
|     default: |     default: | ||||||
|         UNREACHABLE(); |         UNREACHABLE(); | ||||||
|     } |     } | ||||||
|  | @ -195,11 +174,11 @@ void Write(const VAddr vaddr, const T data) { | ||||||
|         break; |         break; | ||||||
|     case PageType::RasterizerCachedMemory: { |     case PageType::RasterizerCachedMemory: { | ||||||
|         RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate); |         RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate); | ||||||
|         std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); |         std::memcpy(GetPointerForRasterizerCache(vaddr), &data, sizeof(T)); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     case PageType::Special: |     case PageType::Special: | ||||||
|         WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); |         WriteMMIO<T>(GetMMIOHandler(*current_page_table, vaddr), vaddr, data); | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         UNREACHABLE(); |         UNREACHABLE(); | ||||||
|  | @ -227,10 +206,6 @@ bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) { | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool IsValidVirtualAddress(const VAddr vaddr) { |  | ||||||
|     return IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(), vaddr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool IsValidPhysicalAddress(const PAddr paddr) { | bool IsValidPhysicalAddress(const PAddr paddr) { | ||||||
|     return GetPhysicalPointer(paddr) != nullptr; |     return GetPhysicalPointer(paddr) != nullptr; | ||||||
| } | } | ||||||
|  | @ -242,7 +217,7 @@ u8* GetPointer(const VAddr vaddr) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) { |     if (current_page_table->attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory) { | ||||||
|         return GetPointerFromVMA(vaddr); |         return GetPointerForRasterizerCache(vaddr); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x}", vaddr); |     LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x{:08x}", vaddr); | ||||||
|  | @ -364,16 +339,9 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) { | ||||||
|                     // space, for example, a system module need not have a VRAM mapping.
 |                     // space, for example, a system module need not have a VRAM mapping.
 | ||||||
|                     break; |                     break; | ||||||
|                 case PageType::RasterizerCachedMemory: { |                 case PageType::RasterizerCachedMemory: { | ||||||
|                     u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); |  | ||||||
|                     if (pointer == nullptr) { |  | ||||||
|                         // It's possible that this function has been called while updating the
 |  | ||||||
|                         // pagetable after unmapping a VMA. In that case the underlying VMA will no
 |  | ||||||
|                         // longer exist, and we should just leave the pagetable entry blank.
 |  | ||||||
|                         page_type = PageType::Unmapped; |  | ||||||
|                     } else { |  | ||||||
|                     page_type = PageType::Memory; |                     page_type = PageType::Memory; | ||||||
|                         current_page_table->pointers[vaddr >> PAGE_BITS] = pointer; |                     current_page_table->pointers[vaddr >> PAGE_BITS] = | ||||||
|                     } |                         GetPointerForRasterizerCache(vaddr & ~PAGE_MASK); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 default: |                 default: | ||||||
|  | @ -501,7 +469,7 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_ | ||||||
|         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(process, current_vaddr), copy_amount); |             std::memcpy(dest_buffer, GetPointerForRasterizerCache(current_vaddr), copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         default: |         default: | ||||||
|  | @ -515,11 +483,6 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_ | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_t size) { |  | ||||||
|     ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), 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); | ||||||
| } | } | ||||||
|  | @ -570,7 +533,7 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi | ||||||
|         case PageType::RasterizerCachedMemory: { |         case PageType::RasterizerCachedMemory: { | ||||||
|             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), |             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), | ||||||
|                                          FlushMode::Invalidate); |                                          FlushMode::Invalidate); | ||||||
|             std::memcpy(GetPointerFromVMA(process, current_vaddr), src_buffer, copy_amount); |             std::memcpy(GetPointerForRasterizerCache(current_vaddr), src_buffer, copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         default: |         default: | ||||||
|  | @ -584,11 +547,6 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) { |  | ||||||
|     WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), dest_addr, src_buffer, |  | ||||||
|                size); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { | void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { | ||||||
|     auto& page_table = process.vm_manager.page_table; |     auto& page_table = process.vm_manager.page_table; | ||||||
|     std::size_t remaining_size = size; |     std::size_t remaining_size = size; | ||||||
|  | @ -624,7 +582,7 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std: | ||||||
|         case PageType::RasterizerCachedMemory: { |         case PageType::RasterizerCachedMemory: { | ||||||
|             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), |             RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount), | ||||||
|                                          FlushMode::Invalidate); |                                          FlushMode::Invalidate); | ||||||
|             std::memset(GetPointerFromVMA(process, current_vaddr), 0, copy_amount); |             std::memset(GetPointerForRasterizerCache(current_vaddr), 0, copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         default: |         default: | ||||||
|  | @ -637,10 +595,6 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std: | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ZeroBlock(const VAddr dest_addr, const std::size_t size) { |  | ||||||
|     ZeroBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), dest_addr, size); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | ||||||
|                const std::size_t size) { |                const std::size_t size) { | ||||||
|     auto& page_table = process.vm_manager.page_table; |     auto& page_table = process.vm_manager.page_table; | ||||||
|  | @ -677,7 +631,8 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | ||||||
|         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); | ||||||
|             WriteBlock(process, dest_addr, GetPointerFromVMA(process, current_vaddr), copy_amount); |             WriteBlock(process, dest_addr, GetPointerForRasterizerCache(current_vaddr), | ||||||
|  |                        copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         default: |         default: | ||||||
|  | @ -692,10 +647,6 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CopyBlock(VAddr dest_addr, VAddr src_addr, const std::size_t size) { |  | ||||||
|     CopyBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), dest_addr, src_addr, size); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, | void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, | ||||||
|                VAddr src_addr, VAddr dest_addr, std::size_t size) { |                VAddr src_addr, VAddr dest_addr, std::size_t size) { | ||||||
|     auto& page_table = src_process.vm_manager.page_table; |     auto& page_table = src_process.vm_manager.page_table; | ||||||
|  | @ -732,7 +683,7 @@ void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_p | ||||||
|         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); | ||||||
|             WriteBlock(dest_process, dest_addr, GetPointerFromVMA(src_process, current_vaddr), |             WriteBlock(dest_process, dest_addr, GetPointerForRasterizerCache(current_vaddr), | ||||||
|                        copy_amount); |                        copy_amount); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -186,7 +186,6 @@ PageTable* GetCurrentPageTable(); | ||||||
| 
 | 
 | ||||||
| /// Determines if the given VAddr is valid for the specified process.
 | /// Determines if the given VAddr is valid for the specified process.
 | ||||||
| bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); | bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); | ||||||
| bool IsValidVirtualAddress(VAddr vaddr); |  | ||||||
| 
 | 
 | ||||||
| bool IsValidPhysicalAddress(PAddr paddr); | bool IsValidPhysicalAddress(PAddr paddr); | ||||||
| 
 | 
 | ||||||
|  | @ -201,14 +200,10 @@ void Write32(VAddr addr, u32 data); | ||||||
| void Write64(VAddr addr, u64 data); | void Write64(VAddr addr, u64 data); | ||||||
| 
 | 
 | ||||||
| void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, std::size_t size); | void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, std::size_t size); | ||||||
| void ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size); |  | ||||||
| void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, | void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, | ||||||
|                 std::size_t size); |                 std::size_t size); | ||||||
| void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size); |  | ||||||
| void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, const std::size_t size); | void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, const std::size_t size); | ||||||
| void ZeroBlock(VAddr dest_addr, const std::size_t size); |  | ||||||
| void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, std::size_t size); | void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, std::size_t size); | ||||||
| void CopyBlock(VAddr dest_addr, VAddr src_addr, std::size_t size); |  | ||||||
| void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, | void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, | ||||||
|                VAddr src_addr, VAddr dest_addr, std::size_t size); |                VAddr src_addr, VAddr dest_addr, std::size_t size); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/arm/arm_interface.h" | #include "core/arm/arm_interface.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
|  | #include "core/hle/kernel/process.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
| #include "core/rpc/packet.h" | #include "core/rpc/packet.h" | ||||||
| #include "core/rpc/rpc_server.h" | #include "core/rpc/rpc_server.h" | ||||||
|  | @ -29,7 +30,8 @@ void RPCServer::HandleReadMemory(Packet& packet, u32 address, u32 data_size) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Note: Memory read occurs asynchronously from the state of the emulator
 |     // Note: Memory read occurs asynchronously from the state of the emulator
 | ||||||
|     Memory::ReadBlock(address, packet.GetPacketData().data(), data_size); |     Memory::ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), address, | ||||||
|  |                       packet.GetPacketData().data(), data_size); | ||||||
|     packet.SetPacketDataSize(data_size); |     packet.SetPacketDataSize(data_size); | ||||||
|     packet.SendReply(); |     packet.SendReply(); | ||||||
| } | } | ||||||
|  | @ -40,7 +42,8 @@ void RPCServer::HandleWriteMemory(Packet& packet, u32 address, const u8* data, u | ||||||
|         (address >= Memory::HEAP_VADDR && address <= Memory::HEAP_VADDR_END) || |         (address >= Memory::HEAP_VADDR && address <= Memory::HEAP_VADDR_END) || | ||||||
|         (address >= Memory::N3DS_EXTRA_RAM_VADDR && address <= Memory::N3DS_EXTRA_RAM_VADDR_END)) { |         (address >= Memory::N3DS_EXTRA_RAM_VADDR && address <= Memory::N3DS_EXTRA_RAM_VADDR_END)) { | ||||||
|         // Note: Memory write occurs asynchronously from the state of the emulator
 |         // Note: Memory write occurs asynchronously from the state of the emulator
 | ||||||
|         Memory::WriteBlock(address, data, data_size); |         Memory::WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), address, data, | ||||||
|  |                            data_size); | ||||||
|         // If the memory happens to be executable code, make sure the changes become visible
 |         // If the memory happens to be executable code, make sure the changes become visible
 | ||||||
|         Core::CPU().InvalidateCacheRange(address, data_size); |         Core::CPU().InvalidateCacheRange(address, data_size); | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue