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…
Reference in a new issue