From 36cf104a024839b1eaa9652fe17997fcac8673b2 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 17 Nov 2018 14:17:20 -0500 Subject: [PATCH 1/9] Memory: replace GetPointerFromVMA with GetPointerForRasterizerCache All usage of GetPointerFromVMA is to recover the pointer that is nulled by changing page type to RasterizerCachedMemory. Our rasterizer cache only works on linear heap and vram, so we can recover the pointer directly by address computation, instead of going through VMA table. Also removed a sanity check pointer!=nullptr in RasterizerMarkRegionCached(RasterizerCachedMemory=>Memory), as now the pointer is never null. The sanity check was added in f2a5a77 (#2797), which was originally necessary during VMA unmapping process, because the function is invloked by VMA after unmapping the page, which in turn invokes back to query the memory, forming a circular dependency. Now the dependency is resolved so the check is not necessary --- src/core/memory.cpp | 73 ++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index d58c6242e..185d9cce2 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -79,37 +79,22 @@ 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) - * using a VMA from the current process + * Gets the pointer for virtual memory where the page is marked as RasterizerCachedMemory. + * 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) { - u8* direct_pointer = nullptr; - - auto& vm_manager = process.vm_manager; - - auto it = vm_manager.FindVMA(vaddr); - ASSERT(it != vm_manager.vma_map.end()); - - auto& vma = it->second; - switch (vma.type) { - case Kernel::VMAType::BackingMemory: - direct_pointer = vma.backing_memory; - break; - case Kernel::VMAType::Free: - return nullptr; - default: - UNREACHABLE(); +static u8* GetPointerForRasterizerCache(VAddr addr) { + if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { + return fcram.data() + (addr - LINEAR_HEAP_VADDR); } - - 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); + if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { + return fcram.data() + (addr - NEW_LINEAR_HEAP_VADDR); + } + if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { + return vram.data() + (addr - VRAM_VADDR); + } + UNREACHABLE(); } /** @@ -159,7 +144,7 @@ T Read(const VAddr vaddr) { RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush); T value; - std::memcpy(&value, GetPointerFromVMA(vaddr), sizeof(T)); + std::memcpy(&value, GetPointerForRasterizerCache(vaddr), sizeof(T)); return value; } case PageType::Special: @@ -195,7 +180,7 @@ void Write(const VAddr vaddr, const T data) { break; case PageType::RasterizerCachedMemory: { RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate); - std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); + std::memcpy(GetPointerForRasterizerCache(vaddr), &data, sizeof(T)); break; } case PageType::Special: @@ -242,7 +227,7 @@ u8* GetPointer(const VAddr vaddr) { } 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); @@ -364,16 +349,9 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached) { // space, for example, a system module need not have a VRAM mapping. break; 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; - current_page_table->pointers[vaddr >> PAGE_BITS] = pointer; - } + page_type = PageType::Memory; + current_page_table->pointers[vaddr >> PAGE_BITS] = + GetPointerForRasterizerCache(vaddr & ~PAGE_MASK); break; } default: @@ -501,7 +479,7 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_ case PageType::RasterizerCachedMemory: { RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), FlushMode::Flush); - std::memcpy(dest_buffer, GetPointerFromVMA(process, current_vaddr), copy_amount); + std::memcpy(dest_buffer, GetPointerForRasterizerCache(current_vaddr), copy_amount); break; } default: @@ -570,7 +548,7 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi case PageType::RasterizerCachedMemory: { RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), FlushMode::Invalidate); - std::memcpy(GetPointerFromVMA(process, current_vaddr), src_buffer, copy_amount); + std::memcpy(GetPointerForRasterizerCache(current_vaddr), src_buffer, copy_amount); break; } default: @@ -624,7 +602,7 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std: case PageType::RasterizerCachedMemory: { RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), FlushMode::Invalidate); - std::memset(GetPointerFromVMA(process, current_vaddr), 0, copy_amount); + std::memset(GetPointerForRasterizerCache(current_vaddr), 0, copy_amount); break; } default: @@ -677,7 +655,8 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, case PageType::RasterizerCachedMemory: { RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), FlushMode::Flush); - WriteBlock(process, dest_addr, GetPointerFromVMA(process, current_vaddr), copy_amount); + WriteBlock(process, dest_addr, GetPointerForRasterizerCache(current_vaddr), + copy_amount); break; } default: @@ -732,7 +711,7 @@ void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_p case PageType::RasterizerCachedMemory: { RasterizerFlushVirtualRegion(current_vaddr, static_cast(copy_amount), FlushMode::Flush); - WriteBlock(dest_process, dest_addr, GetPointerFromVMA(src_process, current_vaddr), + WriteBlock(dest_process, dest_addr, GetPointerForRasterizerCache(current_vaddr), copy_amount); break; } From 7308b8d294145e4a401b8fe5ad03b11d18cc13aa Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 17 Nov 2018 14:31:00 -0500 Subject: [PATCH 2/9] Memory: remove IsValidVirtualAddress with current process --- src/core/gdbstub/gdbstub.cpp | 6 ++++-- src/core/hle/kernel/svc.cpp | 6 +++--- src/core/memory.cpp | 4 ---- src/core/memory.h | 1 - 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 1296b71b4..dcc45ebcf 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -830,7 +830,8 @@ static void ReadMemory() { SendReply("E01"); } - if (!Memory::IsValidVirtualAddress(addr)) { + if (!Memory::IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(), + addr)) { return SendReply("E00"); } @@ -852,7 +853,8 @@ static void WriteMemory() { auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); u32 len = HexToInt(start_offset, static_cast(len_pos - start_offset)); - if (!Memory::IsValidVirtualAddress(addr)) { + if (!Memory::IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(), + addr)) { return SendReply("E00"); } diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index a896f770f..5dd82075d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -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 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; 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) { Thread* thread = kernel.GetThreadManager().GetCurrentThread(); - if (!Memory::IsValidVirtualAddress(handles_address)) + if (!Memory::IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) return ERR_INVALID_POINTER; // 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 server_session, /// 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, Handle reply_target) { - if (!Memory::IsValidVirtualAddress(handles_address)) + if (!Memory::IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) return ERR_INVALID_POINTER; // Check if 'handle_count' is invalid diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 185d9cce2..ed64ee381 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -212,10 +212,6 @@ bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) { return false; } -bool IsValidVirtualAddress(const VAddr vaddr) { - return IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(), vaddr); -} - bool IsValidPhysicalAddress(const PAddr paddr) { return GetPhysicalPointer(paddr) != nullptr; } diff --git a/src/core/memory.h b/src/core/memory.h index aaa44aaa1..15efa6781 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -183,7 +183,6 @@ PageTable* GetCurrentPageTable(); /// Determines if the given VAddr is valid for the specified process. bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); -bool IsValidVirtualAddress(VAddr vaddr); bool IsValidPhysicalAddress(PAddr paddr); From d4ba87d90ae767fcb3b0641e3bcc80bf513f9026 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 17 Nov 2018 14:34:26 -0500 Subject: [PATCH 3/9] Memory: remove GetMMIOHandler with current process --- src/core/memory.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index ed64ee381..f59630940 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -110,12 +110,6 @@ static MMIORegionPointer GetMMIOHandler(const PageTable& page_table, VAddr vaddr 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 T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); @@ -148,7 +142,7 @@ T Read(const VAddr vaddr) { return value; } case PageType::Special: - return ReadMMIO(GetMMIOHandler(vaddr), vaddr); + return ReadMMIO(GetMMIOHandler(*current_page_table, vaddr), vaddr); default: UNREACHABLE(); } @@ -184,7 +178,7 @@ void Write(const VAddr vaddr, const T data) { break; } case PageType::Special: - WriteMMIO(GetMMIOHandler(vaddr), vaddr, data); + WriteMMIO(GetMMIOHandler(*current_page_table, vaddr), vaddr, data); break; default: UNREACHABLE(); From 524364d95ab05e861f4feebd6fc2c1d8bec4fb4f Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 17 Nov 2018 15:01:20 -0500 Subject: [PATCH 4/9] ldr_ro: pass process reference to memory operation Note that not all memory operation is fixed. Specifically, u8/u16/u32 Read/Write is still using the current page tabel --- src/core/hle/service/ldr_ro/cro_helper.cpp | 64 ++++++++++++---------- src/core/hle/service/ldr_ro/cro_helper.h | 28 +++++++--- src/core/hle/service/ldr_ro/ldr_ro.cpp | 12 ++-- 3 files changed, 62 insertions(+), 42 deletions(-) diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp index cd6995c3c..9e6635a69 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.cpp +++ b/src/core/hle/service/ldr_ro/cro_helper.cpp @@ -7,6 +7,7 @@ #include "common/scope_exit.h" #include "core/arm/arm_interface.h" #include "core/core.h" +#include "core/hle/kernel/process.h" #include "core/hle/service/ldr_ro/cro_helper.h" namespace Service::LDR { @@ -120,7 +121,7 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool VAddr relocation_address = batch; while (true) { RelocationEntry relocation; - Memory::ReadBlock(relocation_address, &relocation, sizeof(RelocationEntry)); + Memory::ReadBlock(process, relocation_address, &relocation, sizeof(RelocationEntry)); VAddr relocation_target = SegmentTagToAddress(relocation.target_position); if (relocation_target == 0) { @@ -141,9 +142,9 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool } RelocationEntry relocation; - Memory::ReadBlock(batch, &relocation, sizeof(RelocationEntry)); + Memory::ReadBlock(process, batch, &relocation, sizeof(RelocationEntry)); relocation.is_batch_resolved = reset ? 0 : 1; - Memory::WriteBlock(batch, &relocation, sizeof(RelocationEntry)); + Memory::WriteBlock(process, batch, &relocation, sizeof(RelocationEntry)); return RESULT_SUCCESS; } @@ -547,7 +548,7 @@ ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { static_relocation_table_offset + GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); - CROHelper crs(crs_address); + CROHelper crs(crs_address, process); u32 offset_export_num = GetField(StaticAnonymousSymbolNum); LOG_INFO(Service_LDR, "CRO \"{}\" exports {} static anonymous symbols", ModuleName(), offset_export_num); @@ -753,11 +754,12 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) { GetEntry(i, entry); VAddr relocation_addr = entry.relocation_batch_offset; 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) { ResultCode result = - ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal { + ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal { std::string symbol_name = Memory::ReadCString(entry.name_offset, import_strings_size); u32 symbol_address = source.FindExportNamedSymbol(symbol_name); @@ -795,7 +797,8 @@ ResultCode CROHelper::ResetImportNamedSymbol() { GetEntry(i, entry); VAddr relocation_addr = entry.relocation_batch_offset; 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); if (result.IsError()) { @@ -815,7 +818,8 @@ ResultCode CROHelper::ResetImportIndexedSymbol() { GetEntry(i, entry); VAddr relocation_addr = entry.relocation_batch_offset; 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); if (result.IsError()) { @@ -835,7 +839,8 @@ ResultCode CROHelper::ResetImportAnonymousSymbol() { GetEntry(i, entry); VAddr relocation_addr = entry.relocation_batch_offset; 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); 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); ResultCode result = - ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal { + ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal { if (want_cro_name == source.ModuleName()) { LOG_INFO(Service_LDR, "CRO \"{}\" imports {} indexed symbols from \"{}\"", ModuleName(), entry.import_indexed_symbol_num, source.ModuleName()); for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(j, im); + entry.GetImportIndexedSymbolEntry(process, j, im); ExportIndexedSymbolEntry ex; source.GetEntry(im.index, ex); 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()); for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(j, im); + entry.GetImportAnonymousSymbolEntry(process, j, im); u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); LOG_TRACE(Service_LDR, " Imports 0x{:08X}", symbol_address); ResultCode result = @@ -911,7 +916,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { target.GetEntry(i, entry); VAddr relocation_addr = entry.relocation_batch_offset; 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) { std::string symbol_name = @@ -941,7 +947,8 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { target.GetEntry(i, entry); VAddr relocation_addr = entry.relocation_batch_offset; 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) { std::string symbol_name = @@ -976,7 +983,7 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) { entry.import_indexed_symbol_num, target.ModuleName()); for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(j, im); + entry.GetImportIndexedSymbolEntry(process, j, im); ExportIndexedSymbolEntry ex; GetEntry(im.index, ex); u32 symbol_address = SegmentTagToAddress(ex.symbol_position); @@ -993,7 +1000,7 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) { entry.import_anonymous_symbol_num, target.ModuleName()); for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(j, im); + entry.GetImportAnonymousSymbolEntry(process, j, im); u32 symbol_address = SegmentTagToAddress(im.symbol_position); LOG_TRACE(Service_LDR, " exports symbol 0x{:08X}", symbol_address); ResultCode result = @@ -1025,7 +1032,7 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) { target.ModuleName()); for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { ImportIndexedSymbolEntry im; - entry.GetImportIndexedSymbolEntry(j, im); + entry.GetImportIndexedSymbolEntry(process, j, im); ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); if (result.IsError()) { @@ -1038,7 +1045,7 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) { target.ModuleName()); for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { ImportAnonymousSymbolEntry im; - entry.GetImportAnonymousSymbolEntry(j, im); + entry.GetImportAnonymousSymbolEntry(process, j, im); ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); if (result.IsError()) { @@ -1059,11 +1066,12 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) { GetEntry(i, entry); VAddr relocation_addr = entry.relocation_batch_offset; 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") { ResultCode result = - ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal { + ForEachAutoLinkCRO(process, crs_address, [&](CROHelper source) -> ResultVal { u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); 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 - result = ForEachAutoLinkCRO(crs_address, [this](CROHelper target) -> ResultVal { + result = ForEachAutoLinkCRO(process, crs_address, [this](CROHelper target) -> ResultVal { ResultCode result = ApplyExportNamedSymbol(target); if (result.IsError()) return result; @@ -1335,7 +1343,7 @@ ResultCode CROHelper::Unlink(VAddr crs_address) { // Resets all symbols in other modules imported from this module // Note: the RO service seems only searching in auto-link modules - result = ForEachAutoLinkCRO(crs_address, [this](CROHelper target) -> ResultVal { + result = ForEachAutoLinkCRO(process, crs_address, [this](CROHelper target) -> ResultVal { ResultCode result = ResetExportNamedSymbol(target); if (result.IsError()) return result; @@ -1375,13 +1383,13 @@ void CROHelper::InitCRS() { } void CROHelper::Register(VAddr crs_address, bool auto_link) { - CROHelper crs(crs_address); - CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule()); + CROHelper crs(crs_address, process); + CROHelper head(auto_link ? crs.NextModule() : crs.PreviousModule(), process); if (head.module_address) { // there are already CROs registered // register as the new tail - CROHelper tail(head.PreviousModule()); + CROHelper tail(head.PreviousModule(), process); // link with the old tail ASSERT(tail.NextModule() == 0); @@ -1407,9 +1415,9 @@ void CROHelper::Register(VAddr crs_address, bool auto_link) { } void CROHelper::Unregister(VAddr crs_address) { - CROHelper crs(crs_address); - CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule()); - CROHelper next(NextModule()), previous(PreviousModule()); + CROHelper crs(crs_address, process); + CROHelper next_head(crs.NextModule(), process), previous_head(crs.PreviousModule(), process); + CROHelper next(NextModule(), process), previous(PreviousModule(), process); if (module_address == next_head.module_address || module_address == previous_head.module_address) { diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h index 312ceb402..fe0cb9797 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.h +++ b/src/core/hle/service/ldr_ro/cro_helper.h @@ -11,6 +11,10 @@ #include "core/hle/result.h" #include "core/memory.h" +namespace Kernel { +class Process; +} + namespace Service::LDR { // 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 { public: // 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 { return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize)); @@ -144,6 +149,7 @@ public: private: 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, @@ -311,14 +317,18 @@ private: static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; - void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) { - Memory::ReadBlock(import_indexed_symbol_table_offset + + void GetImportIndexedSymbolEntry(Kernel::Process& process, u32 index, + ImportIndexedSymbolEntry& entry) { + Memory::ReadBlock(process, + import_indexed_symbol_table_offset + index * sizeof(ImportIndexedSymbolEntry), &entry, sizeof(ImportIndexedSymbolEntry)); } - void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) { - Memory::ReadBlock(import_anonymous_symbol_table_offset + + void GetImportAnonymousSymbolEntry(Kernel::Process& process, u32 index, + ImportAnonymousSymbolEntry& entry) { + Memory::ReadBlock(process, + import_anonymous_symbol_table_offset + index * sizeof(ImportAnonymousSymbolEntry), &entry, sizeof(ImportAnonymousSymbolEntry)); } @@ -413,7 +423,8 @@ private: */ template void GetEntry(std::size_t index, T& data) const { - Memory::ReadBlock(GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), + Memory::ReadBlock(process, + GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), &data, sizeof(T)); } @@ -466,10 +477,11 @@ private: * otherwise error code of the last iteration. */ template - static ResultCode ForEachAutoLinkCRO(VAddr crs_address, FunctionObject func) { + static ResultCode ForEachAutoLinkCRO(Kernel::Process& process, VAddr crs_address, + FunctionObject func) { VAddr current = crs_address; while (current != 0) { - CROHelper cro(current); + CROHelper cro(current, process); CASCADE_RESULT(bool next, func(cro)); if (!next) break; diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp index 2cdf505cf..87195ad39 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp @@ -115,7 +115,7 @@ void RO::Initialize(Kernel::HLERequestContext& ctx) { return; } - CROHelper crs(crs_address); + CROHelper crs(crs_address, *process); crs.InitCRS(); 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; } - CROHelper cro(cro_address); + CROHelper cro(cro_address, *process); result = cro.VerifyHash(cro_size, crr_address); 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}", cro_address, zero, cro_buffer_ptr); - CROHelper cro(cro_address); + CROHelper cro(cro_address, *process); 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); - CROHelper cro(cro_address); + CROHelper cro(cro_address, *process); 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); - CROHelper cro(cro_address); + CROHelper cro(cro_address, *process); IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); @@ -487,7 +487,7 @@ void RO::Shutdown(Kernel::HLERequestContext& ctx) { return; } - CROHelper crs(slot->loaded_crs); + CROHelper crs(slot->loaded_crs, *process); crs.Unrebase(true); ResultCode result = RESULT_SUCCESS; From 8871f5a4ac26072f155d0d74850aed4cc7e74356 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 17 Nov 2018 15:01:45 -0500 Subject: [PATCH 5/9] Memory: remove ReadBlock with current process --- src/core/gdbstub/gdbstub.cpp | 6 ++++-- src/core/hle/kernel/svc.cpp | 2 +- src/core/memory.cpp | 5 ----- src/core/memory.h | 1 - src/core/rpc/rpc_server.cpp | 3 ++- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index dcc45ebcf..9e13f9a46 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -836,7 +836,8 @@ static void ReadMemory() { } std::vector data(len); - Memory::ReadBlock(addr, data.data(), len); + Memory::ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, data.data(), + len); MemToGdbHex(reply, data.data(), len); reply[len * 2] = '\0'; @@ -914,7 +915,8 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u32 len) { breakpoint.active = true; breakpoint.addr = addr; 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 btrap{0x70, 0x00, 0x20, 0xe1}; Memory::WriteBlock(addr, btrap.data(), btrap.size()); Core::CPU().ClearInstructionCache(); diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 5dd82075d..2d9466c6f 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -801,7 +801,7 @@ void SVC::OutputDebugString(VAddr address, s32 len) { } std::string string(len, ' '); - Memory::ReadBlock(address, string.data(), len); + Memory::ReadBlock(*kernel.GetCurrentProcess(), address, string.data(), len); LOG_DEBUG(Debug_Emulated, "{}", string); } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index f59630940..25e014253 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -483,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) { Write(addr, data); } diff --git a/src/core/memory.h b/src/core/memory.h index 15efa6781..1e6b6e615 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -197,7 +197,6 @@ void Write32(VAddr addr, u32 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(VAddr src_addr, void* dest_buffer, std::size_t size); void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, std::size_t size); void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size); diff --git a/src/core/rpc/rpc_server.cpp b/src/core/rpc/rpc_server.cpp index 819880196..b9246e922 100644 --- a/src/core/rpc/rpc_server.cpp +++ b/src/core/rpc/rpc_server.cpp @@ -29,7 +29,8 @@ void RPCServer::HandleReadMemory(Packet& packet, u32 address, u32 data_size) { } // 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.SendReply(); } From 4e99641a3b58e92bfe38e7c76b6c88e628ac382a Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 17 Nov 2018 15:06:56 -0500 Subject: [PATCH 6/9] Memory: remove WriteBlock with current process --- src/core/gdbstub/gdbstub.cpp | 9 ++++++--- src/core/hle/service/ldr_ro/cro_helper.h | 3 ++- src/core/memory.cpp | 5 ----- src/core/memory.h | 1 - src/core/rpc/rpc_server.cpp | 3 ++- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 9e13f9a46..55936ed97 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -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 {}", bp->second.len, bp->second.addr, static_cast(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(); p.erase(addr); } @@ -862,7 +863,8 @@ static void WriteMemory() { std::vector data(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(); SendReply("OK"); } @@ -918,7 +920,8 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u32 len) { Memory::ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, breakpoint.inst.data(), breakpoint.inst.size()); static constexpr std::array 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(); p.insert({addr, breakpoint}); diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h index fe0cb9797..f61483bd7 100644 --- a/src/core/hle/service/ldr_ro/cro_helper.h +++ b/src/core/hle/service/ldr_ro/cro_helper.h @@ -437,7 +437,8 @@ private: */ template void SetEntry(std::size_t index, const T& data) { - Memory::WriteBlock(GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), + Memory::WriteBlock(process, + GetField(T::TABLE_OFFSET_FIELD) + static_cast(index * sizeof(T)), &data, sizeof(T)); } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 25e014253..ef3b64c55 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -547,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) { auto& page_table = process.vm_manager.page_table; std::size_t remaining_size = size; diff --git a/src/core/memory.h b/src/core/memory.h index 1e6b6e615..60b102765 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -199,7 +199,6 @@ void Write64(VAddr addr, u64 data); void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer, std::size_t size); void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, 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(VAddr dest_addr, const std::size_t size); void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, std::size_t size); diff --git a/src/core/rpc/rpc_server.cpp b/src/core/rpc/rpc_server.cpp index b9246e922..b3ea1ed42 100644 --- a/src/core/rpc/rpc_server.cpp +++ b/src/core/rpc/rpc_server.cpp @@ -41,7 +41,8 @@ void RPCServer::HandleWriteMemory(Packet& packet, u32 address, const u8* data, u (address >= Memory::HEAP_VADDR && address <= Memory::HEAP_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 - 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 Core::CPU().InvalidateCacheRange(address, data_size); } From 185a83f06d138bdf44cb1931420fe7d0ed1bb322 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 17 Nov 2018 15:11:07 -0500 Subject: [PATCH 7/9] Memory: remove ZeroBlock with current process --- src/core/memory.cpp | 4 ---- src/core/memory.h | 1 - 2 files changed, 5 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index ef3b64c55..238d2d414 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -595,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, const std::size_t size) { auto& page_table = process.vm_manager.page_table; diff --git a/src/core/memory.h b/src/core/memory.h index 60b102765..06f3aed24 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -200,7 +200,6 @@ void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer void WriteBlock(const Kernel::Process& process, 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(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(VAddr dest_addr, VAddr src_addr, std::size_t size); void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, From 679dfd7cdf5e5b5d3dd5618636053d8bffba3699 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 17 Nov 2018 15:24:53 -0500 Subject: [PATCH 8/9] Memory: remove CopyBlock with current process --- src/core/hle/service/gsp/gsp_gpu.cpp | 3 ++- src/core/memory.cpp | 4 ---- src/core/memory.h | 1 - 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/gsp/gsp_gpu.cpp b/src/core/hle/service/gsp/gsp_gpu.cpp index 86b4b47ce..9445aa3c3 100644 --- a/src/core/hle/service/gsp/gsp_gpu.cpp +++ b/src/core/hle/service/gsp/gsp_gpu.cpp @@ -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. // 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); SignalInterrupt(InterruptId::DMA); break; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 238d2d414..f589c765a 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -647,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, VAddr src_addr, VAddr dest_addr, std::size_t size) { auto& page_table = src_process.vm_manager.page_table; diff --git a/src/core/memory.h b/src/core/memory.h index 06f3aed24..42372fbdc 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -201,7 +201,6 @@ void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src std::size_t size); void ZeroBlock(const Kernel::Process& process, 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(VAddr dest_addr, VAddr src_addr, std::size_t size); void CopyBlock(const Kernel::Process& src_process, const Kernel::Process& dest_process, VAddr src_addr, VAddr dest_addr, std::size_t size); From a854b23d9b67fbf6db5b3cbf5f3dcc2b7b7188fd Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Sat, 17 Nov 2018 16:15:34 -0500 Subject: [PATCH 9/9] RPC: add missing include --- src/core/rpc/rpc_server.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/rpc/rpc_server.cpp b/src/core/rpc/rpc_server.cpp index b3ea1ed42..3a8b7f467 100644 --- a/src/core/rpc/rpc_server.cpp +++ b/src/core/rpc/rpc_server.cpp @@ -1,6 +1,7 @@ #include "common/logging/log.h" #include "core/arm/arm_interface.h" #include "core/core.h" +#include "core/hle/kernel/process.h" #include "core/memory.h" #include "core/rpc/packet.h" #include "core/rpc/rpc_server.h"