diff options
| author | 2019-11-26 17:39:57 -0500 | |
|---|---|---|
| committer | 2019-11-26 21:55:39 -0500 | |
| commit | e4c381b8850db96f162cfcf2cbe28b0e7c1f76f1 (patch) | |
| tree | 14b95ea207543f3884558ebdf8673a511bf64dc3 /src | |
| parent | core/memory: Migrate over Read{8, 16, 32, 64, Block} to the Memory class (diff) | |
| download | yuzu-e4c381b8850db96f162cfcf2cbe28b0e7c1f76f1.tar.gz yuzu-e4c381b8850db96f162cfcf2cbe28b0e7c1f76f1.tar.xz yuzu-e4c381b8850db96f162cfcf2cbe28b0e7c1f76f1.zip | |
core/memory: Migrate over Write{8, 16, 32, 64, Block} to the Memory class
The Write functions are used slightly less than the Read functions,
which make these a bit nicer to move over.
The only adjustments we really need to make here are to Dynarmic's
exclusive monitor instance. We need to keep a reference to the currently
active memory instance to perform exclusive read/write operations.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.cpp | 30 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.h | 7 | ||||
| -rw-r--r-- | src/core/core_cpu.cpp | 5 | ||||
| -rw-r--r-- | src/core/core_cpu.h | 18 | ||||
| -rw-r--r-- | src/core/cpu_core_manager.cpp | 2 | ||||
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 27 | ||||
| -rw-r--r-- | src/core/memory.cpp | 220 | ||||
| -rw-r--r-- | src/core/memory.h | 97 | ||||
| -rw-r--r-- | src/core/memory/cheat_engine.cpp | 2 | ||||
| -rw-r--r-- | src/core/tools/freezer.cpp | 8 |
14 files changed, 298 insertions, 153 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 585fb55a9..f8c7f0efd 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp | |||
| @@ -45,20 +45,21 @@ public: | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | void MemoryWrite8(u64 vaddr, u8 value) override { | 47 | void MemoryWrite8(u64 vaddr, u8 value) override { |
| 48 | Memory::Write8(vaddr, value); | 48 | parent.system.Memory().Write8(vaddr, value); |
| 49 | } | 49 | } |
| 50 | void MemoryWrite16(u64 vaddr, u16 value) override { | 50 | void MemoryWrite16(u64 vaddr, u16 value) override { |
| 51 | Memory::Write16(vaddr, value); | 51 | parent.system.Memory().Write16(vaddr, value); |
| 52 | } | 52 | } |
| 53 | void MemoryWrite32(u64 vaddr, u32 value) override { | 53 | void MemoryWrite32(u64 vaddr, u32 value) override { |
| 54 | Memory::Write32(vaddr, value); | 54 | parent.system.Memory().Write32(vaddr, value); |
| 55 | } | 55 | } |
| 56 | void MemoryWrite64(u64 vaddr, u64 value) override { | 56 | void MemoryWrite64(u64 vaddr, u64 value) override { |
| 57 | Memory::Write64(vaddr, value); | 57 | parent.system.Memory().Write64(vaddr, value); |
| 58 | } | 58 | } |
| 59 | void MemoryWrite128(u64 vaddr, Vector value) override { | 59 | void MemoryWrite128(u64 vaddr, Vector value) override { |
| 60 | Memory::Write64(vaddr, value[0]); | 60 | auto& memory = parent.system.Memory(); |
| 61 | Memory::Write64(vaddr + 8, value[1]); | 61 | memory.Write64(vaddr, value[0]); |
| 62 | memory.Write64(vaddr + 8, value[1]); | ||
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | void InterpreterFallback(u64 pc, std::size_t num_instructions) override { | 65 | void InterpreterFallback(u64 pc, std::size_t num_instructions) override { |
| @@ -266,7 +267,9 @@ void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table, | |||
| 266 | jit = MakeJit(page_table, new_address_space_size_in_bits); | 267 | jit = MakeJit(page_table, new_address_space_size_in_bits); |
| 267 | } | 268 | } |
| 268 | 269 | ||
| 269 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(std::size_t core_count) : monitor(core_count) {} | 270 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count) |
| 271 | : monitor(core_count), memory{memory_} {} | ||
| 272 | |||
| 270 | DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; | 273 | DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; |
| 271 | 274 | ||
| 272 | void DynarmicExclusiveMonitor::SetExclusive(std::size_t core_index, VAddr addr) { | 275 | void DynarmicExclusiveMonitor::SetExclusive(std::size_t core_index, VAddr addr) { |
| @@ -279,29 +282,28 @@ void DynarmicExclusiveMonitor::ClearExclusive() { | |||
| 279 | } | 282 | } |
| 280 | 283 | ||
| 281 | bool DynarmicExclusiveMonitor::ExclusiveWrite8(std::size_t core_index, VAddr vaddr, u8 value) { | 284 | bool DynarmicExclusiveMonitor::ExclusiveWrite8(std::size_t core_index, VAddr vaddr, u8 value) { |
| 282 | return monitor.DoExclusiveOperation(core_index, vaddr, 1, | 285 | return monitor.DoExclusiveOperation(core_index, vaddr, 1, [&] { memory.Write8(vaddr, value); }); |
| 283 | [&] { Memory::Write8(vaddr, value); }); | ||
| 284 | } | 286 | } |
| 285 | 287 | ||
| 286 | bool DynarmicExclusiveMonitor::ExclusiveWrite16(std::size_t core_index, VAddr vaddr, u16 value) { | 288 | bool DynarmicExclusiveMonitor::ExclusiveWrite16(std::size_t core_index, VAddr vaddr, u16 value) { |
| 287 | return monitor.DoExclusiveOperation(core_index, vaddr, 2, | 289 | return monitor.DoExclusiveOperation(core_index, vaddr, 2, |
| 288 | [&] { Memory::Write16(vaddr, value); }); | 290 | [&] { memory.Write16(vaddr, value); }); |
| 289 | } | 291 | } |
| 290 | 292 | ||
| 291 | bool DynarmicExclusiveMonitor::ExclusiveWrite32(std::size_t core_index, VAddr vaddr, u32 value) { | 293 | bool DynarmicExclusiveMonitor::ExclusiveWrite32(std::size_t core_index, VAddr vaddr, u32 value) { |
| 292 | return monitor.DoExclusiveOperation(core_index, vaddr, 4, | 294 | return monitor.DoExclusiveOperation(core_index, vaddr, 4, |
| 293 | [&] { Memory::Write32(vaddr, value); }); | 295 | [&] { memory.Write32(vaddr, value); }); |
| 294 | } | 296 | } |
| 295 | 297 | ||
| 296 | bool DynarmicExclusiveMonitor::ExclusiveWrite64(std::size_t core_index, VAddr vaddr, u64 value) { | 298 | bool DynarmicExclusiveMonitor::ExclusiveWrite64(std::size_t core_index, VAddr vaddr, u64 value) { |
| 297 | return monitor.DoExclusiveOperation(core_index, vaddr, 8, | 299 | return monitor.DoExclusiveOperation(core_index, vaddr, 8, |
| 298 | [&] { Memory::Write64(vaddr, value); }); | 300 | [&] { memory.Write64(vaddr, value); }); |
| 299 | } | 301 | } |
| 300 | 302 | ||
| 301 | bool DynarmicExclusiveMonitor::ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) { | 303 | bool DynarmicExclusiveMonitor::ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) { |
| 302 | return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] { | 304 | return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] { |
| 303 | Memory::Write64(vaddr + 0, value[0]); | 305 | memory.Write64(vaddr + 0, value[0]); |
| 304 | Memory::Write64(vaddr + 8, value[1]); | 306 | memory.Write64(vaddr + 8, value[1]); |
| 305 | }); | 307 | }); |
| 306 | } | 308 | } |
| 307 | 309 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index d08de475f..9cd475cfb 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h | |||
| @@ -12,6 +12,10 @@ | |||
| 12 | #include "core/arm/exclusive_monitor.h" | 12 | #include "core/arm/exclusive_monitor.h" |
| 13 | #include "core/arm/unicorn/arm_unicorn.h" | 13 | #include "core/arm/unicorn/arm_unicorn.h" |
| 14 | 14 | ||
| 15 | namespace Memory { | ||
| 16 | class Memory; | ||
| 17 | } | ||
| 18 | |||
| 15 | namespace Core { | 19 | namespace Core { |
| 16 | 20 | ||
| 17 | class ARM_Dynarmic_Callbacks; | 21 | class ARM_Dynarmic_Callbacks; |
| @@ -63,7 +67,7 @@ private: | |||
| 63 | 67 | ||
| 64 | class DynarmicExclusiveMonitor final : public ExclusiveMonitor { | 68 | class DynarmicExclusiveMonitor final : public ExclusiveMonitor { |
| 65 | public: | 69 | public: |
| 66 | explicit DynarmicExclusiveMonitor(std::size_t core_count); | 70 | explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count); |
| 67 | ~DynarmicExclusiveMonitor() override; | 71 | ~DynarmicExclusiveMonitor() override; |
| 68 | 72 | ||
| 69 | void SetExclusive(std::size_t core_index, VAddr addr) override; | 73 | void SetExclusive(std::size_t core_index, VAddr addr) override; |
| @@ -78,6 +82,7 @@ public: | |||
| 78 | private: | 82 | private: |
| 79 | friend class ARM_Dynarmic; | 83 | friend class ARM_Dynarmic; |
| 80 | Dynarmic::A64::ExclusiveMonitor monitor; | 84 | Dynarmic::A64::ExclusiveMonitor monitor; |
| 85 | Memory::Memory& memory; | ||
| 81 | }; | 86 | }; |
| 82 | 87 | ||
| 83 | } // namespace Core | 88 | } // namespace Core |
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 233ea572c..cf3fe0b0b 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp | |||
| @@ -66,9 +66,10 @@ Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_ba | |||
| 66 | 66 | ||
| 67 | Cpu::~Cpu() = default; | 67 | Cpu::~Cpu() = default; |
| 68 | 68 | ||
| 69 | std::unique_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_cores) { | 69 | std::unique_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor( |
| 70 | [[maybe_unused]] Memory::Memory& memory, [[maybe_unused]] std::size_t num_cores) { | ||
| 70 | #ifdef ARCHITECTURE_x86_64 | 71 | #ifdef ARCHITECTURE_x86_64 |
| 71 | return std::make_unique<DynarmicExclusiveMonitor>(num_cores); | 72 | return std::make_unique<DynarmicExclusiveMonitor>(memory, num_cores); |
| 72 | #else | 73 | #else |
| 73 | // TODO(merry): Passthrough exclusive monitor | 74 | // TODO(merry): Passthrough exclusive monitor |
| 74 | return nullptr; | 75 | return nullptr; |
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h index cafca8df7..78f5021a2 100644 --- a/src/core/core_cpu.h +++ b/src/core/core_cpu.h | |||
| @@ -24,6 +24,10 @@ namespace Core::Timing { | |||
| 24 | class CoreTiming; | 24 | class CoreTiming; |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | namespace Memory { | ||
| 28 | class Memory; | ||
| 29 | } | ||
| 30 | |||
| 27 | namespace Core { | 31 | namespace Core { |
| 28 | 32 | ||
| 29 | class ARM_Interface; | 33 | class ARM_Interface; |
| @@ -86,7 +90,19 @@ public: | |||
| 86 | 90 | ||
| 87 | void Shutdown(); | 91 | void Shutdown(); |
| 88 | 92 | ||
| 89 | static std::unique_ptr<ExclusiveMonitor> MakeExclusiveMonitor(std::size_t num_cores); | 93 | /** |
| 94 | * Creates an exclusive monitor to handle exclusive reads/writes. | ||
| 95 | * | ||
| 96 | * @param memory The current memory subsystem that the monitor may wish | ||
| 97 | * to keep track of. | ||
| 98 | * | ||
| 99 | * @param num_cores The number of cores to assume about the CPU. | ||
| 100 | * | ||
| 101 | * @returns The constructed exclusive monitor instance, or nullptr if the current | ||
| 102 | * CPU backend is unable to use an exclusive monitor. | ||
| 103 | */ | ||
| 104 | static std::unique_ptr<ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory, | ||
| 105 | std::size_t num_cores); | ||
| 90 | 106 | ||
| 91 | private: | 107 | private: |
| 92 | void Reschedule(); | 108 | void Reschedule(); |
diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_core_manager.cpp index 8efd410bb..f04a34133 100644 --- a/src/core/cpu_core_manager.cpp +++ b/src/core/cpu_core_manager.cpp | |||
| @@ -25,7 +25,7 @@ CpuCoreManager::~CpuCoreManager() = default; | |||
| 25 | 25 | ||
| 26 | void CpuCoreManager::Initialize() { | 26 | void CpuCoreManager::Initialize() { |
| 27 | barrier = std::make_unique<CpuBarrier>(); | 27 | barrier = std::make_unique<CpuBarrier>(); |
| 28 | exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size()); | 28 | exclusive_monitor = Cpu::MakeExclusiveMonitor(system.Memory(), cores.size()); |
| 29 | 29 | ||
| 30 | for (std::size_t index = 0; index < cores.size(); ++index) { | 30 | for (std::size_t index = 0; index < cores.size(); ++index) { |
| 31 | cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index); | 31 | cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index); |
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 1c74a44d8..37cb28848 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -508,8 +508,9 @@ static void RemoveBreakpoint(BreakpointType type, VAddr addr) { | |||
| 508 | bp->second.len, bp->second.addr, static_cast<int>(type)); | 508 | bp->second.len, bp->second.addr, static_cast<int>(type)); |
| 509 | 509 | ||
| 510 | if (type == BreakpointType::Execute) { | 510 | if (type == BreakpointType::Execute) { |
| 511 | Memory::WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size()); | 511 | auto& system = Core::System::GetInstance(); |
| 512 | Core::System::GetInstance().InvalidateCpuInstructionCaches(); | 512 | system.Memory().WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size()); |
| 513 | system.InvalidateCpuInstructionCaches(); | ||
| 513 | } | 514 | } |
| 514 | p.erase(addr); | 515 | p.erase(addr); |
| 515 | } | 516 | } |
| @@ -993,14 +994,14 @@ static void WriteMemory() { | |||
| 993 | const u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset)); | 994 | const u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset)); |
| 994 | 995 | ||
| 995 | auto& system = Core::System::GetInstance(); | 996 | auto& system = Core::System::GetInstance(); |
| 996 | const auto& memory = system.Memory(); | 997 | auto& memory = system.Memory(); |
| 997 | if (!memory.IsValidVirtualAddress(addr)) { | 998 | if (!memory.IsValidVirtualAddress(addr)) { |
| 998 | return SendReply("E00"); | 999 | return SendReply("E00"); |
| 999 | } | 1000 | } |
| 1000 | 1001 | ||
| 1001 | std::vector<u8> data(len); | 1002 | std::vector<u8> data(len); |
| 1002 | GdbHexToMem(data.data(), len_pos + 1, len); | 1003 | GdbHexToMem(data.data(), len_pos + 1, len); |
| 1003 | Memory::WriteBlock(addr, data.data(), len); | 1004 | memory.WriteBlock(addr, data.data(), len); |
| 1004 | system.InvalidateCpuInstructionCaches(); | 1005 | system.InvalidateCpuInstructionCaches(); |
| 1005 | SendReply("OK"); | 1006 | SendReply("OK"); |
| 1006 | } | 1007 | } |
| @@ -1058,13 +1059,14 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) { | |||
| 1058 | breakpoint.addr = addr; | 1059 | breakpoint.addr = addr; |
| 1059 | breakpoint.len = len; | 1060 | breakpoint.len = len; |
| 1060 | 1061 | ||
| 1061 | auto& memory = Core::System::GetInstance().Memory(); | 1062 | auto& system = Core::System::GetInstance(); |
| 1063 | auto& memory = system.Memory(); | ||
| 1062 | memory.ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size()); | 1064 | memory.ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size()); |
| 1063 | 1065 | ||
| 1064 | static constexpr std::array<u8, 4> btrap{0x00, 0x7d, 0x20, 0xd4}; | 1066 | static constexpr std::array<u8, 4> btrap{0x00, 0x7d, 0x20, 0xd4}; |
| 1065 | if (type == BreakpointType::Execute) { | 1067 | if (type == BreakpointType::Execute) { |
| 1066 | Memory::WriteBlock(addr, btrap.data(), btrap.size()); | 1068 | memory.WriteBlock(addr, btrap.data(), btrap.size()); |
| 1067 | Core::System::GetInstance().InvalidateCpuInstructionCaches(); | 1069 | system.InvalidateCpuInstructionCaches(); |
| 1068 | } | 1070 | } |
| 1069 | p.insert({addr, breakpoint}); | 1071 | p.insert({addr, breakpoint}); |
| 1070 | 1072 | ||
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 07f0dac67..98d07fa5b 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -78,7 +78,7 @@ ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 | |||
| 78 | return ERR_INVALID_STATE; | 78 | return ERR_INVALID_STATE; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | Memory::Write32(address, static_cast<u32>(value + 1)); | 81 | memory.Write32(address, static_cast<u32>(value + 1)); |
| 82 | return SignalToAddressOnly(address, num_to_wake); | 82 | return SignalToAddressOnly(address, num_to_wake); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| @@ -117,7 +117,7 @@ ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr a | |||
| 117 | return ERR_INVALID_STATE; | 117 | return ERR_INVALID_STATE; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | Memory::Write32(address, static_cast<u32>(updated_value)); | 120 | memory.Write32(address, static_cast<u32>(updated_value)); |
| 121 | WakeThreads(waiting_threads, num_to_wake); | 121 | WakeThreads(waiting_threads, num_to_wake); |
| 122 | return RESULT_SUCCESS; | 122 | return RESULT_SUCCESS; |
| 123 | } | 123 | } |
| @@ -151,7 +151,7 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6 | |||
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | if (should_decrement) { | 153 | if (should_decrement) { |
| 154 | Memory::Write32(address, static_cast<u32>(cur_value - 1)); | 154 | memory.Write32(address, static_cast<u32>(cur_value - 1)); |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | // Short-circuit without rescheduling, if timeout is zero. | 157 | // Short-circuit without rescheduling, if timeout is zero. |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 03745c449..8b01567a8 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -274,8 +274,8 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) { | |||
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | // Copy the translated command buffer back into the thread's command buffer area. | 276 | // Copy the translated command buffer back into the thread's command buffer area. |
| 277 | Memory::WriteBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(), | 277 | memory.WriteBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(), |
| 278 | dst_cmdbuf.size() * sizeof(u32)); | 278 | dst_cmdbuf.size() * sizeof(u32)); |
| 279 | 279 | ||
| 280 | return RESULT_SUCCESS; | 280 | return RESULT_SUCCESS; |
| 281 | } | 281 | } |
| @@ -311,10 +311,11 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, | |||
| 311 | size = buffer_size; // TODO(bunnei): This needs to be HW tested | 311 | size = buffer_size; // TODO(bunnei): This needs to be HW tested |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | auto& memory = Core::System::GetInstance().Memory(); | ||
| 314 | if (is_buffer_b) { | 315 | if (is_buffer_b) { |
| 315 | Memory::WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); | 316 | memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); |
| 316 | } else { | 317 | } else { |
| 317 | Memory::WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); | 318 | memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); |
| 318 | } | 319 | } |
| 319 | 320 | ||
| 320 | return size; | 321 | return size; |
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 88eede436..061e9bcb0 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -117,7 +117,7 @@ ResultCode Mutex::Release(VAddr address) { | |||
| 117 | 117 | ||
| 118 | // There are no more threads waiting for the mutex, release it completely. | 118 | // There are no more threads waiting for the mutex, release it completely. |
| 119 | if (thread == nullptr) { | 119 | if (thread == nullptr) { |
| 120 | Memory::Write32(address, 0); | 120 | system.Memory().Write32(address, 0); |
| 121 | return RESULT_SUCCESS; | 121 | return RESULT_SUCCESS; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| @@ -132,7 +132,7 @@ ResultCode Mutex::Release(VAddr address) { | |||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | // Grant the mutex to the next waiting thread and resume it. | 134 | // Grant the mutex to the next waiting thread and resume it. |
| 135 | Memory::Write32(address, mutex_value); | 135 | system.Memory().Write32(address, mutex_value); |
| 136 | 136 | ||
| 137 | ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex); | 137 | ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex); |
| 138 | thread->ResumeFromWait(); | 138 | thread->ResumeFromWait(); |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index a6c377cfc..db3ae3eb8 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -1120,7 +1120,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, H | |||
| 1120 | std::fill(ctx.vector_registers.begin() + 16, ctx.vector_registers.end(), u128{}); | 1120 | std::fill(ctx.vector_registers.begin() + 16, ctx.vector_registers.end(), u128{}); |
| 1121 | } | 1121 | } |
| 1122 | 1122 | ||
| 1123 | Memory::WriteBlock(thread_context, &ctx, sizeof(ctx)); | 1123 | system.Memory().WriteBlock(thread_context, &ctx, sizeof(ctx)); |
| 1124 | return RESULT_SUCCESS; | 1124 | return RESULT_SUCCESS; |
| 1125 | } | 1125 | } |
| 1126 | 1126 | ||
| @@ -1280,20 +1280,21 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add | |||
| 1280 | return ERR_INVALID_HANDLE; | 1280 | return ERR_INVALID_HANDLE; |
| 1281 | } | 1281 | } |
| 1282 | 1282 | ||
| 1283 | auto& memory = system.Memory(); | ||
| 1283 | const auto& vm_manager = process->VMManager(); | 1284 | const auto& vm_manager = process->VMManager(); |
| 1284 | const MemoryInfo memory_info = vm_manager.QueryMemory(address); | 1285 | const MemoryInfo memory_info = vm_manager.QueryMemory(address); |
| 1285 | 1286 | ||
| 1286 | Memory::Write64(memory_info_address, memory_info.base_address); | 1287 | memory.Write64(memory_info_address, memory_info.base_address); |
| 1287 | Memory::Write64(memory_info_address + 8, memory_info.size); | 1288 | memory.Write64(memory_info_address + 8, memory_info.size); |
| 1288 | Memory::Write32(memory_info_address + 16, memory_info.state); | 1289 | memory.Write32(memory_info_address + 16, memory_info.state); |
| 1289 | Memory::Write32(memory_info_address + 20, memory_info.attributes); | 1290 | memory.Write32(memory_info_address + 20, memory_info.attributes); |
| 1290 | Memory::Write32(memory_info_address + 24, memory_info.permission); | 1291 | memory.Write32(memory_info_address + 24, memory_info.permission); |
| 1291 | Memory::Write32(memory_info_address + 32, memory_info.ipc_ref_count); | 1292 | memory.Write32(memory_info_address + 32, memory_info.ipc_ref_count); |
| 1292 | Memory::Write32(memory_info_address + 28, memory_info.device_ref_count); | 1293 | memory.Write32(memory_info_address + 28, memory_info.device_ref_count); |
| 1293 | Memory::Write32(memory_info_address + 36, 0); | 1294 | memory.Write32(memory_info_address + 36, 0); |
| 1294 | 1295 | ||
| 1295 | // Page info appears to be currently unused by the kernel and is always set to zero. | 1296 | // Page info appears to be currently unused by the kernel and is always set to zero. |
| 1296 | Memory::Write32(page_info_address, 0); | 1297 | memory.Write32(page_info_address, 0); |
| 1297 | 1298 | ||
| 1298 | return RESULT_SUCCESS; | 1299 | return RESULT_SUCCESS; |
| 1299 | } | 1300 | } |
| @@ -2290,12 +2291,13 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes, | |||
| 2290 | return ERR_INVALID_ADDRESS_STATE; | 2291 | return ERR_INVALID_ADDRESS_STATE; |
| 2291 | } | 2292 | } |
| 2292 | 2293 | ||
| 2294 | auto& memory = system.Memory(); | ||
| 2293 | const auto& process_list = kernel.GetProcessList(); | 2295 | const auto& process_list = kernel.GetProcessList(); |
| 2294 | const auto num_processes = process_list.size(); | 2296 | const auto num_processes = process_list.size(); |
| 2295 | const auto copy_amount = std::min(std::size_t{out_process_ids_size}, num_processes); | 2297 | const auto copy_amount = std::min(std::size_t{out_process_ids_size}, num_processes); |
| 2296 | 2298 | ||
| 2297 | for (std::size_t i = 0; i < copy_amount; ++i) { | 2299 | for (std::size_t i = 0; i < copy_amount; ++i) { |
| 2298 | Memory::Write64(out_process_ids, process_list[i]->GetProcessID()); | 2300 | memory.Write64(out_process_ids, process_list[i]->GetProcessID()); |
| 2299 | out_process_ids += sizeof(u64); | 2301 | out_process_ids += sizeof(u64); |
| 2300 | } | 2302 | } |
| 2301 | 2303 | ||
| @@ -2329,13 +2331,14 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd | |||
| 2329 | return ERR_INVALID_ADDRESS_STATE; | 2331 | return ERR_INVALID_ADDRESS_STATE; |
| 2330 | } | 2332 | } |
| 2331 | 2333 | ||
| 2334 | auto& memory = system.Memory(); | ||
| 2332 | const auto& thread_list = current_process->GetThreadList(); | 2335 | const auto& thread_list = current_process->GetThreadList(); |
| 2333 | const auto num_threads = thread_list.size(); | 2336 | const auto num_threads = thread_list.size(); |
| 2334 | const auto copy_amount = std::min(std::size_t{out_thread_ids_size}, num_threads); | 2337 | const auto copy_amount = std::min(std::size_t{out_thread_ids_size}, num_threads); |
| 2335 | 2338 | ||
| 2336 | auto list_iter = thread_list.cbegin(); | 2339 | auto list_iter = thread_list.cbegin(); |
| 2337 | for (std::size_t i = 0; i < copy_amount; ++i, ++list_iter) { | 2340 | for (std::size_t i = 0; i < copy_amount; ++i, ++list_iter) { |
| 2338 | Memory::Write64(out_thread_ids, (*list_iter)->GetThreadID()); | 2341 | memory.Write64(out_thread_ids, (*list_iter)->GetThreadID()); |
| 2339 | out_thread_ids += sizeof(u64); | 2342 | out_thread_ids += sizeof(u64); |
| 2340 | } | 2343 | } |
| 2341 | 2344 | ||
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 699c48107..5c940a82e 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -58,35 +58,6 @@ u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) { | |||
| 58 | u8* GetPointerFromVMA(VAddr vaddr) { | 58 | u8* GetPointerFromVMA(VAddr vaddr) { |
| 59 | return ::Memory::GetPointerFromVMA(*Core::System::GetInstance().CurrentProcess(), vaddr); | 59 | return ::Memory::GetPointerFromVMA(*Core::System::GetInstance().CurrentProcess(), vaddr); |
| 60 | } | 60 | } |
| 61 | |||
| 62 | template <typename T> | ||
| 63 | void Write(const VAddr vaddr, const T data) { | ||
| 64 | u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||
| 65 | if (page_pointer != nullptr) { | ||
| 66 | // NOTE: Avoid adding any extra logic to this fast-path block | ||
| 67 | std::memcpy(&page_pointer[vaddr & PAGE_MASK], &data, sizeof(T)); | ||
| 68 | return; | ||
| 69 | } | ||
| 70 | |||
| 71 | Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | ||
| 72 | switch (type) { | ||
| 73 | case Common::PageType::Unmapped: | ||
| 74 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, | ||
| 75 | static_cast<u32>(data), vaddr); | ||
| 76 | return; | ||
| 77 | case Common::PageType::Memory: | ||
| 78 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); | ||
| 79 | break; | ||
| 80 | case Common::PageType::RasterizerCachedMemory: { | ||
| 81 | u8* const host_ptr{GetPointerFromVMA(vaddr)}; | ||
| 82 | Core::System::GetInstance().GPU().InvalidateRegion(ToCacheAddr(host_ptr), sizeof(T)); | ||
| 83 | std::memcpy(host_ptr, &data, sizeof(T)); | ||
| 84 | break; | ||
| 85 | } | ||
| 86 | default: | ||
| 87 | UNREACHABLE(); | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } // Anonymous namespace | 61 | } // Anonymous namespace |
| 91 | 62 | ||
| 92 | // Implementation class used to keep the specifics of the memory subsystem hidden | 63 | // Implementation class used to keep the specifics of the memory subsystem hidden |
| @@ -195,6 +166,22 @@ struct Memory::Impl { | |||
| 195 | return Read<u64_le>(addr); | 166 | return Read<u64_le>(addr); |
| 196 | } | 167 | } |
| 197 | 168 | ||
| 169 | void Write8(const VAddr addr, const u8 data) { | ||
| 170 | Write<u8>(addr, data); | ||
| 171 | } | ||
| 172 | |||
| 173 | void Write16(const VAddr addr, const u16 data) { | ||
| 174 | Write<u16_le>(addr, data); | ||
| 175 | } | ||
| 176 | |||
| 177 | void Write32(const VAddr addr, const u32 data) { | ||
| 178 | Write<u32_le>(addr, data); | ||
| 179 | } | ||
| 180 | |||
| 181 | void Write64(const VAddr addr, const u64 data) { | ||
| 182 | Write<u64_le>(addr, data); | ||
| 183 | } | ||
| 184 | |||
| 198 | std::string ReadCString(VAddr vaddr, std::size_t max_length) { | 185 | std::string ReadCString(VAddr vaddr, std::size_t max_length) { |
| 199 | std::string string; | 186 | std::string string; |
| 200 | string.reserve(max_length); | 187 | string.reserve(max_length); |
| @@ -259,6 +246,53 @@ struct Memory::Impl { | |||
| 259 | ReadBlock(*system.CurrentProcess(), src_addr, dest_buffer, size); | 246 | ReadBlock(*system.CurrentProcess(), src_addr, dest_buffer, size); |
| 260 | } | 247 | } |
| 261 | 248 | ||
| 249 | void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, | ||
| 250 | const std::size_t size) { | ||
| 251 | const auto& page_table = process.VMManager().page_table; | ||
| 252 | std::size_t remaining_size = size; | ||
| 253 | std::size_t page_index = dest_addr >> PAGE_BITS; | ||
| 254 | std::size_t page_offset = dest_addr & PAGE_MASK; | ||
| 255 | |||
| 256 | while (remaining_size > 0) { | ||
| 257 | const std::size_t copy_amount = | ||
| 258 | std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size); | ||
| 259 | const auto current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); | ||
| 260 | |||
| 261 | switch (page_table.attributes[page_index]) { | ||
| 262 | case Common::PageType::Unmapped: { | ||
| 263 | LOG_ERROR(HW_Memory, | ||
| 264 | "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 265 | current_vaddr, dest_addr, size); | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | case Common::PageType::Memory: { | ||
| 269 | DEBUG_ASSERT(page_table.pointers[page_index]); | ||
| 270 | |||
| 271 | u8* const dest_ptr = page_table.pointers[page_index] + page_offset; | ||
| 272 | std::memcpy(dest_ptr, src_buffer, copy_amount); | ||
| 273 | break; | ||
| 274 | } | ||
| 275 | case Common::PageType::RasterizerCachedMemory: { | ||
| 276 | u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); | ||
| 277 | system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount); | ||
| 278 | std::memcpy(host_ptr, src_buffer, copy_amount); | ||
| 279 | break; | ||
| 280 | } | ||
| 281 | default: | ||
| 282 | UNREACHABLE(); | ||
| 283 | } | ||
| 284 | |||
| 285 | page_index++; | ||
| 286 | page_offset = 0; | ||
| 287 | src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; | ||
| 288 | remaining_size -= copy_amount; | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | void WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) { | ||
| 293 | WriteBlock(*system.CurrentProcess(), dest_addr, src_buffer, size); | ||
| 294 | } | ||
| 295 | |||
| 262 | void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { | 296 | void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { |
| 263 | const auto& page_table = process.VMManager().page_table; | 297 | const auto& page_table = process.VMManager().page_table; |
| 264 | std::size_t remaining_size = size; | 298 | std::size_t remaining_size = size; |
| @@ -501,6 +535,46 @@ struct Memory::Impl { | |||
| 501 | return {}; | 535 | return {}; |
| 502 | } | 536 | } |
| 503 | 537 | ||
| 538 | /** | ||
| 539 | * Writes a particular data type to memory at the given virtual address. | ||
| 540 | * | ||
| 541 | * @param vaddr The virtual address to write the data type to. | ||
| 542 | * | ||
| 543 | * @tparam T The data type to write to memory. This type *must* be | ||
| 544 | * trivially copyable, otherwise the behavior of this function | ||
| 545 | * is undefined. | ||
| 546 | * | ||
| 547 | * @returns The instance of T write to the specified virtual address. | ||
| 548 | */ | ||
| 549 | template <typename T> | ||
| 550 | void Write(const VAddr vaddr, const T data) { | ||
| 551 | u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||
| 552 | if (page_pointer != nullptr) { | ||
| 553 | // NOTE: Avoid adding any extra logic to this fast-path block | ||
| 554 | std::memcpy(&page_pointer[vaddr & PAGE_MASK], &data, sizeof(T)); | ||
| 555 | return; | ||
| 556 | } | ||
| 557 | |||
| 558 | const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; | ||
| 559 | switch (type) { | ||
| 560 | case Common::PageType::Unmapped: | ||
| 561 | LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, | ||
| 562 | static_cast<u32>(data), vaddr); | ||
| 563 | return; | ||
| 564 | case Common::PageType::Memory: | ||
| 565 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); | ||
| 566 | break; | ||
| 567 | case Common::PageType::RasterizerCachedMemory: { | ||
| 568 | u8* const host_ptr{GetPointerFromVMA(vaddr)}; | ||
| 569 | system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), sizeof(T)); | ||
| 570 | std::memcpy(host_ptr, &data, sizeof(T)); | ||
| 571 | break; | ||
| 572 | } | ||
| 573 | default: | ||
| 574 | UNREACHABLE(); | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 504 | Core::System& system; | 578 | Core::System& system; |
| 505 | }; | 579 | }; |
| 506 | 580 | ||
| @@ -562,6 +636,22 @@ u64 Memory::Read64(const VAddr addr) { | |||
| 562 | return impl->Read64(addr); | 636 | return impl->Read64(addr); |
| 563 | } | 637 | } |
| 564 | 638 | ||
| 639 | void Memory::Write8(VAddr addr, u8 data) { | ||
| 640 | impl->Write8(addr, data); | ||
| 641 | } | ||
| 642 | |||
| 643 | void Memory::Write16(VAddr addr, u16 data) { | ||
| 644 | impl->Write16(addr, data); | ||
| 645 | } | ||
| 646 | |||
| 647 | void Memory::Write32(VAddr addr, u32 data) { | ||
| 648 | impl->Write32(addr, data); | ||
| 649 | } | ||
| 650 | |||
| 651 | void Memory::Write64(VAddr addr, u64 data) { | ||
| 652 | impl->Write64(addr, data); | ||
| 653 | } | ||
| 654 | |||
| 565 | std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) { | 655 | std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) { |
| 566 | return impl->ReadCString(vaddr, max_length); | 656 | return impl->ReadCString(vaddr, max_length); |
| 567 | } | 657 | } |
| @@ -575,6 +665,15 @@ void Memory::ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_ | |||
| 575 | impl->ReadBlock(src_addr, dest_buffer, size); | 665 | impl->ReadBlock(src_addr, dest_buffer, size); |
| 576 | } | 666 | } |
| 577 | 667 | ||
| 668 | void Memory::WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, | ||
| 669 | std::size_t size) { | ||
| 670 | impl->WriteBlock(process, dest_addr, src_buffer, size); | ||
| 671 | } | ||
| 672 | |||
| 673 | void Memory::WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) { | ||
| 674 | impl->WriteBlock(dest_addr, src_buffer, size); | ||
| 675 | } | ||
| 676 | |||
| 578 | void Memory::ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size) { | 677 | void Memory::ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size) { |
| 579 | impl->ZeroBlock(process, dest_addr, size); | 678 | impl->ZeroBlock(process, dest_addr, size); |
| 580 | } | 679 | } |
| @@ -612,67 +711,4 @@ bool IsKernelVirtualAddress(const VAddr vaddr) { | |||
| 612 | return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; | 711 | return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; |
| 613 | } | 712 | } |
| 614 | 713 | ||
| 615 | void Write8(const VAddr addr, const u8 data) { | ||
| 616 | Write<u8>(addr, data); | ||
| 617 | } | ||
| 618 | |||
| 619 | void Write16(const VAddr addr, const u16 data) { | ||
| 620 | Write<u16_le>(addr, data); | ||
| 621 | } | ||
| 622 | |||
| 623 | void Write32(const VAddr addr, const u32 data) { | ||
| 624 | Write<u32_le>(addr, data); | ||
| 625 | } | ||
| 626 | |||
| 627 | void Write64(const VAddr addr, const u64 data) { | ||
| 628 | Write<u64_le>(addr, data); | ||
| 629 | } | ||
| 630 | |||
| 631 | void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, | ||
| 632 | const std::size_t size) { | ||
| 633 | const auto& page_table = process.VMManager().page_table; | ||
| 634 | std::size_t remaining_size = size; | ||
| 635 | std::size_t page_index = dest_addr >> PAGE_BITS; | ||
| 636 | std::size_t page_offset = dest_addr & PAGE_MASK; | ||
| 637 | |||
| 638 | while (remaining_size > 0) { | ||
| 639 | const std::size_t copy_amount = | ||
| 640 | std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size); | ||
| 641 | const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); | ||
| 642 | |||
| 643 | switch (page_table.attributes[page_index]) { | ||
| 644 | case Common::PageType::Unmapped: { | ||
| 645 | LOG_ERROR(HW_Memory, | ||
| 646 | "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 647 | current_vaddr, dest_addr, size); | ||
| 648 | break; | ||
| 649 | } | ||
| 650 | case Common::PageType::Memory: { | ||
| 651 | DEBUG_ASSERT(page_table.pointers[page_index]); | ||
| 652 | |||
| 653 | u8* dest_ptr = page_table.pointers[page_index] + page_offset; | ||
| 654 | std::memcpy(dest_ptr, src_buffer, copy_amount); | ||
| 655 | break; | ||
| 656 | } | ||
| 657 | case Common::PageType::RasterizerCachedMemory: { | ||
| 658 | const auto& host_ptr{GetPointerFromVMA(process, current_vaddr)}; | ||
| 659 | Core::System::GetInstance().GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount); | ||
| 660 | std::memcpy(host_ptr, src_buffer, copy_amount); | ||
| 661 | break; | ||
| 662 | } | ||
| 663 | default: | ||
| 664 | UNREACHABLE(); | ||
| 665 | } | ||
| 666 | |||
| 667 | page_index++; | ||
| 668 | page_offset = 0; | ||
| 669 | src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; | ||
| 670 | remaining_size -= copy_amount; | ||
| 671 | } | ||
| 672 | } | ||
| 673 | |||
| 674 | void WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) { | ||
| 675 | WriteBlock(*Core::System::GetInstance().CurrentProcess(), dest_addr, src_buffer, size); | ||
| 676 | } | ||
| 677 | |||
| 678 | } // namespace Memory | 714 | } // namespace Memory |
diff --git a/src/core/memory.h b/src/core/memory.h index cc6ab920e..7878f3fb1 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -193,6 +193,50 @@ public: | |||
| 193 | u64 Read64(VAddr addr); | 193 | u64 Read64(VAddr addr); |
| 194 | 194 | ||
| 195 | /** | 195 | /** |
| 196 | * Writes an 8-bit unsigned integer to the given virtual address in | ||
| 197 | * the current process' address space. | ||
| 198 | * | ||
| 199 | * @param addr The virtual address to write the 8-bit unsigned integer to. | ||
| 200 | * @param data The 8-bit unsigned integer to write to the given virtual address. | ||
| 201 | * | ||
| 202 | * @post The memory at the given virtual address contains the specified data value. | ||
| 203 | */ | ||
| 204 | void Write8(VAddr addr, u8 data); | ||
| 205 | |||
| 206 | /** | ||
| 207 | * Writes a 16-bit unsigned integer to the given virtual address in | ||
| 208 | * the current process' address space. | ||
| 209 | * | ||
| 210 | * @param addr The virtual address to write the 16-bit unsigned integer to. | ||
| 211 | * @param data The 16-bit unsigned integer to write to the given virtual address. | ||
| 212 | * | ||
| 213 | * @post The memory range [addr, sizeof(data)) contains the given data value. | ||
| 214 | */ | ||
| 215 | void Write16(VAddr addr, u16 data); | ||
| 216 | |||
| 217 | /** | ||
| 218 | * Writes a 32-bit unsigned integer to the given virtual address in | ||
| 219 | * the current process' address space. | ||
| 220 | * | ||
| 221 | * @param addr The virtual address to write the 32-bit unsigned integer to. | ||
| 222 | * @param data The 32-bit unsigned integer to write to the given virtual address. | ||
| 223 | * | ||
| 224 | * @post The memory range [addr, sizeof(data)) contains the given data value. | ||
| 225 | */ | ||
| 226 | void Write32(VAddr addr, u32 data); | ||
| 227 | |||
| 228 | /** | ||
| 229 | * Writes a 64-bit unsigned integer to the given virtual address in | ||
| 230 | * the current process' address space. | ||
| 231 | * | ||
| 232 | * @param addr The virtual address to write the 64-bit unsigned integer to. | ||
| 233 | * @param data The 64-bit unsigned integer to write to the given virtual address. | ||
| 234 | * | ||
| 235 | * @post The memory range [addr, sizeof(data)) contains the given data value. | ||
| 236 | */ | ||
| 237 | void Write64(VAddr addr, u64 data); | ||
| 238 | |||
| 239 | /** | ||
| 196 | * Reads a null-terminated string from the given virtual address. | 240 | * Reads a null-terminated string from the given virtual address. |
| 197 | * This function will continually read characters until either: | 241 | * This function will continually read characters until either: |
| 198 | * | 242 | * |
| @@ -248,6 +292,50 @@ public: | |||
| 248 | void ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size); | 292 | void ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size); |
| 249 | 293 | ||
| 250 | /** | 294 | /** |
| 295 | * Writes a range of bytes into a given process' address space at the specified | ||
| 296 | * virtual address. | ||
| 297 | * | ||
| 298 | * @param process The process to write data into the address space of. | ||
| 299 | * @param dest_addr The destination virtual address to begin writing the data at. | ||
| 300 | * @param src_buffer The data to write into the process' address space. | ||
| 301 | * @param size The size of the data to write, in bytes. | ||
| 302 | * | ||
| 303 | * @post The address range [dest_addr, size) in the process' address space | ||
| 304 | * contains the data that was within src_buffer. | ||
| 305 | * | ||
| 306 | * @post If an attempt is made to write into an unmapped region of memory, the writes | ||
| 307 | * will be ignored and an error will be logged. | ||
| 308 | * | ||
| 309 | * @post If a write is performed into a region of memory that is considered cached | ||
| 310 | * rasterizer memory, will cause the currently active rasterizer to be notified | ||
| 311 | * and will mark that region as invalidated to caches that the active | ||
| 312 | * graphics backend may be maintaining over the course of execution. | ||
| 313 | */ | ||
| 314 | void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, | ||
| 315 | std::size_t size); | ||
| 316 | |||
| 317 | /** | ||
| 318 | * Writes a range of bytes into the current process' address space at the specified | ||
| 319 | * virtual address. | ||
| 320 | * | ||
| 321 | * @param dest_addr The destination virtual address to begin writing the data at. | ||
| 322 | * @param src_buffer The data to write into the current process' address space. | ||
| 323 | * @param size The size of the data to write, in bytes. | ||
| 324 | * | ||
| 325 | * @post The address range [dest_addr, size) in the current process' address space | ||
| 326 | * contains the data that was within src_buffer. | ||
| 327 | * | ||
| 328 | * @post If an attempt is made to write into an unmapped region of memory, the writes | ||
| 329 | * will be ignored and an error will be logged. | ||
| 330 | * | ||
| 331 | * @post If a write is performed into a region of memory that is considered cached | ||
| 332 | * rasterizer memory, will cause the currently active rasterizer to be notified | ||
| 333 | * and will mark that region as invalidated to caches that the active | ||
| 334 | * graphics backend may be maintaining over the course of execution. | ||
| 335 | */ | ||
| 336 | void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size); | ||
| 337 | |||
| 338 | /** | ||
| 251 | * Fills the specified address range within a process' address space with zeroes. | 339 | * Fills the specified address range within a process' address space with zeroes. |
| 252 | * | 340 | * |
| 253 | * @param process The process that will have a portion of its memory zeroed out. | 341 | * @param process The process that will have a portion of its memory zeroed out. |
| @@ -320,13 +408,4 @@ void SetCurrentPageTable(Kernel::Process& process); | |||
| 320 | /// Determines if the given VAddr is a kernel address | 408 | /// Determines if the given VAddr is a kernel address |
| 321 | bool IsKernelVirtualAddress(VAddr vaddr); | 409 | bool IsKernelVirtualAddress(VAddr vaddr); |
| 322 | 410 | ||
| 323 | void Write8(VAddr addr, u8 data); | ||
| 324 | void Write16(VAddr addr, u16 data); | ||
| 325 | void Write32(VAddr addr, u32 data); | ||
| 326 | void Write64(VAddr addr, u64 data); | ||
| 327 | |||
| 328 | void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, | ||
| 329 | std::size_t size); | ||
| 330 | void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size); | ||
| 331 | |||
| 332 | } // namespace Memory | 411 | } // namespace Memory |
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index d6745af8b..d1e6bed93 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -30,7 +30,7 @@ void StandardVmCallbacks::MemoryRead(VAddr address, void* data, u64 size) { | |||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size) { | 32 | void StandardVmCallbacks::MemoryWrite(VAddr address, const void* data, u64 size) { |
| 33 | WriteBlock(SanitizeAddress(address), data, size); | 33 | system.Memory().WriteBlock(SanitizeAddress(address), data, size); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | u64 StandardVmCallbacks::HidKeysDown() { | 36 | u64 StandardVmCallbacks::HidKeysDown() { |
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp index ab66f35f9..55e0dbc49 100644 --- a/src/core/tools/freezer.cpp +++ b/src/core/tools/freezer.cpp | |||
| @@ -34,16 +34,16 @@ u64 MemoryReadWidth(Memory::Memory& memory, u32 width, VAddr addr) { | |||
| 34 | void MemoryWriteWidth(Memory::Memory& memory, u32 width, VAddr addr, u64 value) { | 34 | void MemoryWriteWidth(Memory::Memory& memory, u32 width, VAddr addr, u64 value) { |
| 35 | switch (width) { | 35 | switch (width) { |
| 36 | case 1: | 36 | case 1: |
| 37 | Memory::Write8(addr, static_cast<u8>(value)); | 37 | memory.Write8(addr, static_cast<u8>(value)); |
| 38 | break; | 38 | break; |
| 39 | case 2: | 39 | case 2: |
| 40 | Memory::Write16(addr, static_cast<u16>(value)); | 40 | memory.Write16(addr, static_cast<u16>(value)); |
| 41 | break; | 41 | break; |
| 42 | case 4: | 42 | case 4: |
| 43 | Memory::Write32(addr, static_cast<u32>(value)); | 43 | memory.Write32(addr, static_cast<u32>(value)); |
| 44 | break; | 44 | break; |
| 45 | case 8: | 45 | case 8: |
| 46 | Memory::Write64(addr, value); | 46 | memory.Write64(addr, value); |
| 47 | break; | 47 | break; |
| 48 | default: | 48 | default: |
| 49 | UNREACHABLE(); | 49 | UNREACHABLE(); |