diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 1296b71b4..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); } @@ -830,12 +831,14 @@ static void ReadMemory() { SendReply("E01"); } - if (!Memory::IsValidVirtualAddress(addr)) { + if (!Memory::IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(), + addr)) { return SendReply("E00"); } 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'; @@ -852,14 +855,16 @@ 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"); } 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"); } @@ -912,9 +917,11 @@ 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()); + 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/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index ce69b2d6a..465ba76a5 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 @@ -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/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/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..f61483bd7 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)); } @@ -426,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)); } @@ -466,10 +478,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; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index d58c6242e..f589c765a 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(); } /** @@ -125,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); @@ -159,11 +138,11 @@ 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: - return ReadMMIO(GetMMIOHandler(vaddr), vaddr); + return ReadMMIO(GetMMIOHandler(*current_page_table, vaddr), vaddr); default: UNREACHABLE(); } @@ -195,11 +174,11 @@ 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: - WriteMMIO(GetMMIOHandler(vaddr), vaddr, data); + WriteMMIO(GetMMIOHandler(*current_page_table, vaddr), vaddr, data); break; default: UNREACHABLE(); @@ -227,10 +206,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; } @@ -242,7 +217,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 +339,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 +469,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: @@ -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) { Write(addr, data); } @@ -570,7 +533,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: @@ -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) { auto& page_table = process.vm_manager.page_table; 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: { 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: @@ -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, const std::size_t size) { 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: { 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: @@ -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, VAddr src_addr, VAddr dest_addr, std::size_t size) { 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: { 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; } diff --git a/src/core/memory.h b/src/core/memory.h index ec43c8663..dcefb369e 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -186,7 +186,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); @@ -201,14 +200,10 @@ 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); 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, VAddr src_addr, VAddr dest_addr, std::size_t size); diff --git a/src/core/rpc/rpc_server.cpp b/src/core/rpc/rpc_server.cpp index 819880196..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" @@ -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 - 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(); } @@ -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::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); }