From c084fc824cf4e076bb83e41af64f5cfaa9204dcb Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 08:46:11 +0100 Subject: [PATCH 01/17] Memory: IsValidVirtualAddress/IsValidPhysicalAddress --- src/core/memory.cpp | 21 +++++++++++++++++++++ src/core/memory.h | 3 +++ src/core/mmio.h | 2 ++ 3 files changed, 26 insertions(+) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index ee9b69f814..68a29b1547 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -246,6 +246,26 @@ void Write(const VAddr vaddr, const T data) { } } +bool IsValidVirtualAddress(const VAddr vaddr) { + const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + if (page_pointer) + return true; + + if (current_page_table->attributes[vaddr >> PAGE_BITS] != PageType::Special) + return false; + + MMIORegionPointer mmio_region = GetMMIOHandler(vaddr); + if (mmio_region) { + return mmio_region->IsValidAddress(vaddr); + } + + return false; +} + +bool IsValidPhysicalAddress(const PAddr paddr) { + return IsValidVirtualAddress(PhysicalToVirtualAddress(paddr)); +} + u8* GetPointer(const VAddr vaddr) { u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; if (page_pointer) { @@ -261,6 +281,7 @@ u8* GetPointer(const VAddr vaddr) { } u8* GetPhysicalPointer(PAddr address) { + // TODO(Subv): This call should not go through the application's memory mapping. return GetPointer(PhysicalToVirtualAddress(address)); } diff --git a/src/core/memory.h b/src/core/memory.h index 126d60471e..9ada78fc84 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -110,6 +110,9 @@ enum : VAddr { NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, }; +bool IsValidVirtualAddress(const VAddr addr); +bool IsValidPhysicalAddress(const PAddr addr); + u8 Read8(VAddr addr); u16 Read16(VAddr addr); u32 Read32(VAddr addr); diff --git a/src/core/mmio.h b/src/core/mmio.h index 06b555e989..cb644f51b4 100644 --- a/src/core/mmio.h +++ b/src/core/mmio.h @@ -18,6 +18,8 @@ class MMIORegion { public: virtual ~MMIORegion() = default; + virtual bool IsValidAddress(VAddr addr) = 0; + virtual u8 Read8(VAddr addr) = 0; virtual u16 Read16(VAddr addr) = 0; virtual u32 Read32(VAddr addr) = 0; From 3873b36db333547152280b741e85aa54c69d8199 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 09:14:18 +0100 Subject: [PATCH 02/17] Memory: ReadBlock/WriteBlock --- src/core/memory.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++-- src/core/memory.h | 4 ++- src/core/mmio.h | 4 +++ 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 68a29b1547..c7b99a4670 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -364,6 +364,45 @@ u64 Read64(const VAddr addr) { return Read(addr); } +void ReadBlock(const VAddr src_addr, u8* dest_buffer, const size_t size) { + size_t remaining_size = size; + size_t page_index = src_addr >> PAGE_BITS; + size_t page_offset = src_addr & PAGE_MASK; + + while (remaining_size > 0) { + const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); + const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + + switch (current_page_table->attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); + std::memset(dest_buffer, 0, copy_amount); + break; + } + case PageType::Memory: { + DEBUG_ASSERT(current_page_table->pointers[page_index]); + + const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; + std::memcpy(dest_buffer, src_ptr, copy_amount); + break; + } + case PageType::Special: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); + break; + } + default: + UNREACHABLE(); + } + + page_index++; + page_offset = 0; + dest_buffer += copy_amount; + remaining_size -= copy_amount; + } +} + void Write8(const VAddr addr, const u8 data) { Write(addr, data); } @@ -380,9 +419,41 @@ void Write64(const VAddr addr, const u64 data) { Write(addr, data); } -void WriteBlock(const VAddr addr, const u8* data, const size_t size) { - for (u32 offset = 0; offset < size; offset++) { - Write8(addr + offset, data[offset]); +void WriteBlock(const VAddr dest_addr, const u8* src_buffer, const size_t size) { + size_t remaining_size = size; + size_t page_index = dest_addr >> PAGE_BITS; + size_t page_offset = dest_addr & PAGE_MASK; + + while (remaining_size > 0) { + const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); + const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + + switch (current_page_table->attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); + break; + } + case PageType::Memory: { + DEBUG_ASSERT(current_page_table->pointers[page_index]); + + u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; + std::memcpy(dest_ptr, src_buffer, copy_amount); + break; + } + case PageType::Special: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); + break; + } + default: + UNREACHABLE(); + } + + page_index++; + page_offset = 0; + src_buffer += copy_amount; + remaining_size -= copy_amount; } } diff --git a/src/core/memory.h b/src/core/memory.h index 9ada78fc84..35bd5eb0cd 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -118,12 +118,14 @@ u16 Read16(VAddr addr); u32 Read32(VAddr addr); u64 Read64(VAddr addr); +void ReadBlock(const VAddr src_addr, u8* dest_buffer, size_t size); + void Write8(VAddr addr, u8 data); void Write16(VAddr addr, u16 data); void Write32(VAddr addr, u32 data); void Write64(VAddr addr, u64 data); -void WriteBlock(VAddr addr, const u8* data, size_t size); +void WriteBlock(const VAddr dest_addr, const u8* src_buffer, size_t size); u8* GetPointer(VAddr virtual_address); diff --git a/src/core/mmio.h b/src/core/mmio.h index cb644f51b4..35b73b061c 100644 --- a/src/core/mmio.h +++ b/src/core/mmio.h @@ -25,10 +25,14 @@ public: virtual u32 Read32(VAddr addr) = 0; virtual u64 Read64(VAddr addr) = 0; + virtual bool ReadBlock(VAddr src_addr, u8* dest_buffer, size_t size) = 0; + virtual void Write8(VAddr addr, u8 data) = 0; virtual void Write16(VAddr addr, u16 data) = 0; virtual void Write32(VAddr addr, u32 data) = 0; virtual void Write64(VAddr addr, u64 data) = 0; + + virtual bool WriteBlock(VAddr dest_addr, const u8* src_buffer, size_t size) = 0; }; using MMIORegionPointer = std::shared_ptr; From b3b3dd7591416319ee0d6c4d32065bb5a7b1209f Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 09:48:46 +0100 Subject: [PATCH 03/17] Debugger/Callstack: Replace Memory::GetPointer with Memory::IsValidVirtualAddress --- src/citra_qt/debugger/callstack.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index 793944639e..1a30774958 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp @@ -37,10 +37,13 @@ void CallstackWidget::OnDebugModeEntered() int counter = 0; for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { + if (!Memory::IsValidVirtualAddress(addr)) + break; + const u32 ret_addr = Memory::Read32(addr); const u32 call_addr = ret_addr - 4; //get call address??? - if (Memory::GetPointer(call_addr) == nullptr) + if (!Memory::IsValidVirtualAddress(call_addr)) break; /* TODO (mattvail) clean me, move to debugger interface */ From 2be17a0c6e0a386b78e09dc6341182d3fe605d41 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 10:01:43 +0100 Subject: [PATCH 04/17] FileSys/Path: Replace Memory::GetPointer with Memory::ReadBlock --- src/core/file_sys/archive_backend.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp index 97adf0e122..cc0aa70227 100644 --- a/src/core/file_sys/archive_backend.cpp +++ b/src/core/file_sys/archive_backend.cpp @@ -19,22 +19,22 @@ Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { switch (type) { case Binary: { - u8* data = Memory::GetPointer(pointer); - binary = std::vector(data, data + size); + binary.resize(size); + Memory::ReadBlock(pointer, binary.data(), binary.size()); break; } case Char: { - const char* data = reinterpret_cast(Memory::GetPointer(pointer)); - string = std::string(data, size - 1); // Data is always null-terminated. + string.resize(size - 1); // Data is always null-terminated. + Memory::ReadBlock(pointer, &string[0], string.size()); break; } case Wchar: { - const char16_t* data = reinterpret_cast(Memory::GetPointer(pointer)); - u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. + u16str.resize(size / 2 - 1); // Data is always null-terminated. + Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); break; } From ca17df5757f08c7bb673aec19e0fdd4698dd904f Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 10:21:41 +0100 Subject: [PATCH 05/17] Memory: ZeroBlock --- src/core/memory.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/core/memory.h | 1 + 2 files changed, 39 insertions(+) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index c7b99a4670..1604a7da5d 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -457,6 +457,44 @@ void WriteBlock(const VAddr dest_addr, const u8* src_buffer, const size_t size) } } +void ZeroBlock(const VAddr dest_addr, const size_t size) { + size_t remaining_size = size; + size_t page_index = dest_addr >> PAGE_BITS; + size_t page_offset = dest_addr & PAGE_MASK; + + while (remaining_size > 0) { + const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); + const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + + switch (current_page_table->attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); + break; + } + case PageType::Memory: { + DEBUG_ASSERT(current_page_table->pointers[page_index]); + + u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; + std::memset(dest_ptr, 0, copy_amount); + break; + } + case PageType::Special: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + static const std::array zeros = {}; + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); + break; + } + default: + UNREACHABLE(); + } + + page_index++; + page_offset = 0; + remaining_size -= copy_amount; + } +} + template<> u8 ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr) { return mmio_handler->Read8(addr); diff --git a/src/core/memory.h b/src/core/memory.h index 35bd5eb0cd..713cdfb2f4 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -126,6 +126,7 @@ void Write32(VAddr addr, u32 data); void Write64(VAddr addr, u64 data); void WriteBlock(const VAddr dest_addr, const u8* src_buffer, size_t size); +void ZeroBlock(const VAddr dest_addr, const size_t size); u8* GetPointer(VAddr virtual_address); From aa84cab4e9c27c947192d055dd06941415d6e590 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 10:11:10 +0100 Subject: [PATCH 06/17] Applets/swkdb: Remove use of Memory::GetPointer --- src/core/hle/applets/swkbd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp index 90c6adc656..3ad950692e 100644 --- a/src/core/hle/applets/swkbd.cpp +++ b/src/core/hle/applets/swkbd.cpp @@ -99,7 +99,7 @@ void SoftwareKeyboard::DrawScreenKeyboard() { auto info = bottom_screen->framebuffer_info[bottom_screen->index]; // TODO(Subv): Draw the HLE keyboard, for now just zero-fill the framebuffer - memset(Memory::GetPointer(info.address_left), 0, info.stride * 320); + Memory::ZeroBlock(info.address_left, info.stride * 320); GSP_GPU::SetBufferSwap(1, info); } From 1ebaaf9bb1f5f663f53edaeac026fb465a8c576e Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 10:27:32 +0100 Subject: [PATCH 07/17] Kernel/Thread: Remove use of Memory::GetPointer --- src/core/hle/kernel/thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 43def61463..3f6bec5fae 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -403,7 +403,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, priority = new_priority; } - if (!Memory::GetPointer(entry_point)) { + if (!Memory::IsValidVirtualAddress(entry_point)) { LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); // TODO: Verify error return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, From fddd243b17edb0fe03ef1a85c2abdf95353a534d Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 11:18:49 +0100 Subject: [PATCH 08/17] APT: Remove use of Memory::GetPointer --- src/core/hle/applets/mii_selector.cpp | 21 +++++++++++---------- src/core/hle/applets/mii_selector.h | 4 +++- src/core/hle/applets/swkbd.cpp | 15 +++++++-------- src/core/hle/service/apt/apt.cpp | 25 +++++++++++++------------ src/core/hle/service/apt/apt.h | 6 ++---- 5 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp index bf39eca221..77f01d2088 100644 --- a/src/core/hle/applets/mii_selector.cpp +++ b/src/core/hle/applets/mii_selector.cpp @@ -32,9 +32,9 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. // Create the SharedMemory that will hold the framebuffer data Service::APT::CaptureBufferInfo capture_info; - ASSERT(sizeof(capture_info) == parameter.buffer_size); + ASSERT(sizeof(capture_info) == parameter.buffer.size()); - memcpy(&capture_info, parameter.data, sizeof(capture_info)); + memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); using Kernel::MemoryPermission; // Allocate a heap block of the required size for this applet. @@ -47,8 +47,7 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p // Send the response message with the newly created SharedMemory Service::APT::MessageParameter result; result.signal = static_cast(Service::APT::SignalType::LibAppFinished); - result.data = nullptr; - result.buffer_size = 0; + result.buffer.clear(); result.destination_id = static_cast(Service::APT::AppletId::Application); result.sender_id = static_cast(id); result.object = framebuffer_memory; @@ -63,15 +62,17 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. // TODO(Subv): Reverse the parameter format for the Mii Selector - if(parameter.buffer_size >= sizeof(u32)) { - // TODO: defaults return no error, but garbage in other unknown fields - memset(parameter.data, 0, sizeof(u32)); - } + memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); + + // TODO(Subv): Find more about this structure, result code 0 is enough to let most games continue. + MiiResult result; + memset(&result, 0, sizeof(result)); + result.result_code = 0; // Let the application know that we're closing Service::APT::MessageParameter message; - message.buffer_size = parameter.buffer_size; - message.data = parameter.data; + message.buffer.resize(sizeof(MiiResult)); + std::memcpy(message.buffer.data(), &result, message.buffer.size()); message.signal = static_cast(Service::APT::SignalType::LibAppClosed); message.destination_id = static_cast(Service::APT::AppletId::Application); message.sender_id = static_cast(id); diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h index be6b04642a..24e8e721da 100644 --- a/src/core/hle/applets/mii_selector.h +++ b/src/core/hle/applets/mii_selector.h @@ -24,7 +24,7 @@ struct MiiConfig { u8 unk_004; INSERT_PADDING_BYTES(3); u16 unk_008; - INSERT_PADDING_BYTES(0x8C - 0xA); + INSERT_PADDING_BYTES(0x82); u8 unk_08C; INSERT_PADDING_BYTES(3); u16 unk_090; @@ -75,6 +75,8 @@ public: /// Whether this applet is currently running instead of the host application or not. bool started; + + MiiConfig config; }; } diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp index 3ad950692e..d87bf3d57b 100644 --- a/src/core/hle/applets/swkbd.cpp +++ b/src/core/hle/applets/swkbd.cpp @@ -35,9 +35,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. // Create the SharedMemory that will hold the framebuffer data Service::APT::CaptureBufferInfo capture_info; - ASSERT(sizeof(capture_info) == parameter.buffer_size); + ASSERT(sizeof(capture_info) == parameter.buffer.size()); - memcpy(&capture_info, parameter.data, sizeof(capture_info)); + memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); using Kernel::MemoryPermission; // Allocate a heap block of the required size for this applet. @@ -50,8 +50,7 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con // Send the response message with the newly created SharedMemory Service::APT::MessageParameter result; result.signal = static_cast(Service::APT::SignalType::LibAppFinished); - result.data = nullptr; - result.buffer_size = 0; + result.buffer.clear(); result.destination_id = static_cast(Service::APT::AppletId::Application); result.sender_id = static_cast(id); result.object = framebuffer_memory; @@ -61,9 +60,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con } ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { - ASSERT_MSG(parameter.buffer_size == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); + ASSERT_MSG(parameter.buffer.size() == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); - memcpy(&config, parameter.data, parameter.buffer_size); + memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); text_memory = boost::static_pointer_cast(parameter.object); // TODO(Subv): Verify if this is the correct behavior @@ -107,8 +106,8 @@ void SoftwareKeyboard::DrawScreenKeyboard() { void SoftwareKeyboard::Finalize() { // Let the application know that we're closing Service::APT::MessageParameter message; - message.buffer_size = sizeof(SoftwareKeyboardConfig); - message.data = reinterpret_cast(&config); + message.buffer.resize(sizeof(SoftwareKeyboardConfig)); + std::memcpy(message.buffer.data(), &config, message.buffer.size()); message.signal = static_cast(Service::APT::SignalType::LibAppClosed); message.destination_id = static_cast(Service::APT::AppletId::Application); message.sender_id = static_cast(id); diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 73fce60795..e2304fa54a 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -176,12 +176,12 @@ void SendParameter(Service::Interface* self) { } MessageParameter param; - param.buffer_size = buffer_size; param.destination_id = dst_app_id; param.sender_id = src_app_id; param.object = Kernel::g_handle_table.GetGeneric(handle); param.signal = signal_type; - param.data = Memory::GetPointer(buffer); + param.buffer.resize(buffer_size); + Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size()); cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; @@ -199,16 +199,15 @@ void ReceiveParameter(Service::Interface* self) { cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = next_parameter.sender_id; cmd_buff[3] = next_parameter.signal; // Signal type - cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size + cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size cmd_buff[5] = 0x10; cmd_buff[6] = 0; if (next_parameter.object != nullptr) cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); - cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; + cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; cmd_buff[8] = buffer; - if (next_parameter.data) - memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); + Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); } @@ -222,16 +221,15 @@ void GlanceParameter(Service::Interface* self) { cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = next_parameter.sender_id; cmd_buff[3] = next_parameter.signal; // Signal type - cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size + cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size cmd_buff[5] = 0x10; cmd_buff[6] = 0; if (next_parameter.object != nullptr) cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); - cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; + cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; cmd_buff[8] = buffer; - if (next_parameter.data) - memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); + Memory::WriteBlock(buffer, next_parameter.buffer.data(), std::min(static_cast(buffer_size), next_parameter.buffer.size())); LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); } @@ -365,10 +363,13 @@ void StartLibraryApplet(Service::Interface* self) { return; } + size_t buffer_size = cmd_buff[2]; + VAddr buffer_addr = cmd_buff[6]; + AppletStartupParameter parameter; - parameter.buffer_size = cmd_buff[2]; parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]); - parameter.data = Memory::GetPointer(cmd_buff[6]); + parameter.buffer.resize(buffer_size); + Memory::ReadBlock(buffer_addr, parameter.buffer.data(), parameter.buffer.size()); cmd_buff[1] = applet->Start(parameter).raw; } diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 1a1034fcce..66cda1d4c9 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -20,16 +20,14 @@ struct MessageParameter { u32 sender_id = 0; u32 destination_id = 0; u32 signal = 0; - u32 buffer_size = 0; Kernel::SharedPtr object = nullptr; - u8* data = nullptr; + std::vector buffer; }; /// Holds information about the parameters used in StartLibraryApplet struct AppletStartupParameter { - u32 buffer_size = 0; Kernel::SharedPtr object = nullptr; - u8* data = nullptr; + std::vector buffer; }; /// Used by the application to pass information about the current framebuffer to applets. From 64068583fbefb7268a1138828611d735eae1e212 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 11:51:48 +0100 Subject: [PATCH 09/17] CFG: Remove use of Memory::GetPointer --- src/core/hle/service/cfg/cfg.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index b9322c55d6..3921653e5d 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -191,28 +191,32 @@ void GetConfigInfoBlk2(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 size = cmd_buff[1]; u32 block_id = cmd_buff[2]; - u8* data_pointer = Memory::GetPointer(cmd_buff[4]); + VAddr data_pointer = cmd_buff[4]; - if (data_pointer == nullptr) { + if (!Memory::IsValidVirtualAddress(data_pointer)) { cmd_buff[1] = -1; // TODO(Subv): Find the right error code return; } - cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw; + std::vector data(size); + cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data.data()).raw; + Memory::WriteBlock(data_pointer, data.data(), data.size()); } void GetConfigInfoBlk8(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 size = cmd_buff[1]; u32 block_id = cmd_buff[2]; - u8* data_pointer = Memory::GetPointer(cmd_buff[4]); + VAddr data_pointer = cmd_buff[4]; - if (data_pointer == nullptr) { + if (!Memory::IsValidVirtualAddress(data_pointer)) { cmd_buff[1] = -1; // TODO(Subv): Find the right error code return; } - cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw; + std::vector data(size); + cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data.data()).raw; + Memory::WriteBlock(data_pointer, data.data(), data.size()); } void UpdateConfigNANDSavegame(Service::Interface* self) { From 896e5009aeec0603ee3dd77e34462a503253b75f Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 12:49:35 +0100 Subject: [PATCH 10/17] FS/Archive: Remove use of Memory::GetPointer --- src/core/hle/service/fs/archive.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index cc51ede0c0..a7ebfde254 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -108,11 +108,13 @@ ResultVal File::SyncRequest() { offset, length, backend->GetSize()); } - ResultVal read = backend->Read(offset, length, Memory::GetPointer(address)); + std::vector data(length); + ResultVal read = backend->Read(offset, data.size(), data.data()); if (read.Failed()) { cmd_buff[1] = read.Code().raw; return read.Code(); } + Memory::WriteBlock(address, data.data(), *read); cmd_buff[2] = static_cast(*read); Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(address), length); break; @@ -128,7 +130,9 @@ ResultVal File::SyncRequest() { LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); - ResultVal written = backend->Write(offset, length, flush != 0, Memory::GetPointer(address)); + std::vector data(length); + Memory::ReadBlock(address, data.data(), data.size()); + ResultVal written = backend->Write(offset, data.size(), flush != 0, data.data()); if (written.Failed()) { cmd_buff[1] = written.Code().raw; return written.Code(); @@ -216,12 +220,14 @@ ResultVal Directory::SyncRequest() { { u32 count = cmd_buff[1]; u32 address = cmd_buff[3]; - auto entries = reinterpret_cast(Memory::GetPointer(address)); + std::vector entries(count); LOG_TRACE(Service_FS, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(), count); // Number of entries actually read - cmd_buff[2] = backend->Read(count, entries); + u32 read = backend->Read(entries.size(), entries.data()); + cmd_buff[2] = read; + Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); break; } @@ -456,11 +462,12 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon if (result.IsError()) return result; - u8* smdh_icon = Memory::GetPointer(icon_buffer); - if (!smdh_icon) + if (!Memory::IsValidVirtualAddress(icon_buffer)) return ResultCode(-1); // TODO(Subv): Find the right error code - ext_savedata->WriteIcon(path, smdh_icon, icon_size); + std::vector smdh_icon(icon_size); + Memory::ReadBlock(icon_buffer, smdh_icon.data(), smdh_icon.size()); + ext_savedata->WriteIcon(path, smdh_icon.data(), smdh_icon.size()); return RESULT_SUCCESS; } From e936f5952cd1de5db2758747396666a380843d9d Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 12:54:33 +0100 Subject: [PATCH 11/17] DSP_DSP: Remove use of Memory::GetPointer --- src/core/hle/service/dsp_dsp.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 10730d7ac6..c8aadd9dbc 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -140,12 +140,15 @@ static void LoadComponent(Service::Interface* self) { // TODO(bunnei): Implement real DSP firmware loading - ASSERT(Memory::GetPointer(buffer) != nullptr); - ASSERT(size > 0x37C); + ASSERT(Memory::IsValidVirtualAddress(buffer)); - LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer), size)); + std::vector component_data(size); + Memory::ReadBlock(buffer, component_data.data(), component_data.size()); + + LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(component_data.data(), component_data.size())); // Some versions of the firmware have the location of DSP structures listed here. - LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer) + 0x340, 60)); + ASSERT(size > 0x37C); + LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(component_data.data() + 0x340, 60)); LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", size, prog_mask, data_mask, buffer); @@ -285,7 +288,7 @@ static void WriteProcessPipe(Service::Interface* self) { return; } - ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe_index, size, buffer); + ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); std::vector message(size); for (u32 i = 0; i < size; i++) { @@ -324,7 +327,7 @@ static void ReadPipeIfPossible(Service::Interface* self) { DSP::HLE::DspPipe pipe = static_cast(pipe_index); - ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); + ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -364,7 +367,7 @@ static void ReadPipe(Service::Interface* self) { DSP::HLE::DspPipe pipe = static_cast(pipe_index); - ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); + ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { std::vector response = DSP::HLE::PipeRead(pipe, size); From 31d49e01094068519850bbfa414f314fdb27beee Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 15:22:45 +0100 Subject: [PATCH 12/17] Memory: CopyBlock --- src/core/memory.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/core/memory.h | 4 ++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 1604a7da5d..bf2493270d 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -495,6 +495,47 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { } } +void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { + size_t remaining_size = size; + size_t page_index = src_addr >> PAGE_BITS; + size_t page_offset = src_addr & PAGE_MASK; + + while (remaining_size > 0) { + const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); + const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + + switch (current_page_table->attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); + ZeroBlock(dest_addr, copy_amount); + break; + } + case PageType::Memory: { + DEBUG_ASSERT(current_page_table->pointers[page_index]); + const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; + WriteBlock(dest_addr, src_ptr, copy_amount); + break; + } + case PageType::Special: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + std::vector buffer(copy_amount); + GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); + WriteBlock(dest_addr, buffer.data(), buffer.size()); + break; + } + default: + UNREACHABLE(); + } + + page_index++; + page_offset = 0; + dest_addr += copy_amount; + src_addr += copy_amount; + remaining_size -= copy_amount; + } +} + template<> u8 ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr) { return mmio_handler->Read8(addr); diff --git a/src/core/memory.h b/src/core/memory.h index 713cdfb2f4..bb5dd0d153 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -118,15 +118,15 @@ u16 Read16(VAddr addr); u32 Read32(VAddr addr); u64 Read64(VAddr addr); -void ReadBlock(const VAddr src_addr, u8* dest_buffer, size_t size); - void Write8(VAddr addr, u8 data); void Write16(VAddr addr, u16 data); void Write32(VAddr addr, u32 data); void Write64(VAddr addr, u64 data); +void ReadBlock(const VAddr src_addr, u8* dest_buffer, size_t size); void WriteBlock(const VAddr dest_addr, const u8* src_buffer, size_t size); void ZeroBlock(const VAddr dest_addr, const size_t size); +void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size); u8* GetPointer(VAddr virtual_address); From 5f33d2cf07d94af5304ec64371a404e709a9805f Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 15:24:14 +0100 Subject: [PATCH 13/17] GSP_GPU: Remove use of Memory::GetPointer --- src/core/hle/service/gsp_gpu.cpp | 85 +++++++++++++++++++------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 8ded9b09bc..f3c7b7df31 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -65,15 +65,27 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { return reinterpret_cast(ptr); } +/** + * Writes a single GSP GPU hardware registers with a single u32 value + * (For internal use.) + * + * @param base_address The address of the register in question + * @param data Data to be written + */ +static void WriteSingleHWReg(u32 base_address, u32 data) { + DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000, "Write address out of range or misaligned"); + HW::Write(base_address + REGS_BEGIN, data); +} + /** * Writes sequential GSP GPU hardware registers using an array of source data * * @param base_address The address of the first register in the sequence * @param size_in_bytes The number of registers to update (size of data) - * @param data A pointer to the source data + * @param data_vaddr A pointer to the source data * @return RESULT_SUCCESS if the parameters are valid, error code otherwise */ -static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { +static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_vaddr) { // This magic number is verified to be done by the gsp module const u32 max_size_in_bytes = 0x80; @@ -87,10 +99,10 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da return ERR_GSP_REGS_MISALIGNED; } else { while (size_in_bytes > 0) { - HW::Write(base_address + REGS_BEGIN, *data); + WriteSingleHWReg(base_address, Memory::Read32(data_vaddr)); size_in_bytes -= 4; - ++data; + data_vaddr += 4; base_address += 4; } return RESULT_SUCCESS; @@ -112,7 +124,7 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da * @param masks A pointer to the masks * @return RESULT_SUCCESS if the parameters are valid, error code otherwise */ -static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) { +static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, VAddr masks_vaddr) { // This magic number is verified to be done by the gsp module const u32 max_size_in_bytes = 0x80; @@ -131,14 +143,17 @@ static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32 reg_value; HW::Read(reg_value, reg_address); - // Update the current value of the register only for set mask bits - reg_value = (reg_value & ~*masks) | (*data | *masks); + u32 data = Memory::Read32(data_vaddr); + u32 mask = Memory::Read32(masks_vaddr); - HW::Write(reg_address, reg_value); + // Update the current value of the register only for set mask bits + reg_value = (reg_value & ~mask) | (data | mask); + + WriteSingleHWReg(base_address, reg_value); size_in_bytes -= 4; - ++data; - ++masks; + data_vaddr += 4; + masks_vaddr += 4; base_address += 4; } return RESULT_SUCCESS; @@ -164,8 +179,7 @@ static void WriteHWRegs(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 reg_addr = cmd_buff[1]; u32 size = cmd_buff[2]; - - u32* src = (u32*)Memory::GetPointer(cmd_buff[4]); + VAddr src = cmd_buff[4]; cmd_buff[1] = WriteHWRegs(reg_addr, size, src).raw; } @@ -186,8 +200,8 @@ static void WriteHWRegsWithMask(Service::Interface* self) { u32 reg_addr = cmd_buff[1]; u32 size = cmd_buff[2]; - u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]); - u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]); + VAddr src_data = cmd_buff[4]; + VAddr mask_data = cmd_buff[6]; cmd_buff[1] = WriteHWRegsWithMask(reg_addr, size, src_data, mask_data).raw; } @@ -210,13 +224,16 @@ static void ReadHWRegs(Service::Interface* self) { return; } - u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); + VAddr dst_vaddr = cmd_buff[0x41]; while (size > 0) { - HW::Read(*dst, reg_addr + REGS_BEGIN); + u32 value; + HW::Read(value, reg_addr + REGS_BEGIN); + + Memory::Write32(dst_vaddr, value); size -= 4; - ++dst; + dst_vaddr += 4; reg_addr += 4; } } @@ -226,22 +243,22 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); if (info.active_fb == 0) { - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), - 4, &phys_address_left); - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), - 4, &phys_address_right); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), + phys_address_left); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), + phys_address_right); } else { - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), - 4, &phys_address_left); - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), - 4, &phys_address_right); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), + phys_address_left); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), + phys_address_right); } - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), - 4, &info.stride); - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), - 4, &info.format); - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), - 4, &info.shown_fb); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), + info.stride); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), + info.format); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), + info.shown_fb); if (Pica::g_debug_context) Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); @@ -432,9 +449,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), command.dma_request.size); - memcpy(Memory::GetPointer(command.dma_request.dest_address), - Memory::GetPointer(command.dma_request.source_address), - command.dma_request.size); + // TODO(Subv): These memory accesses should not go through the application's memory mapping. + // They should go through the GSP module's memory mapping. + Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, command.dma_request.size); SignalInterrupt(InterruptId::DMA); break; } From 59b268de35d7ed9db55e2aadc449e945e896b937 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 15:24:39 +0100 Subject: [PATCH 14/17] SSL_C: Remove use of Memory::GetPointer --- src/core/hle/service/ssl_c.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp index 14a4e98ec4..a8aff1abfc 100644 --- a/src/core/hle/service/ssl_c.cpp +++ b/src/core/hle/service/ssl_c.cpp @@ -31,7 +31,6 @@ static void GenerateRandomData(Service::Interface* self) { u32 size = cmd_buff[1]; VAddr address = cmd_buff[3]; - u8* output_buff = Memory::GetPointer(address); // Fill the output buffer with random data. u32 data = 0; @@ -44,13 +43,13 @@ static void GenerateRandomData(Service::Interface* self) { if (size > 4) { // Use up the entire 4 bytes of the random data for as long as possible - *(u32*)(output_buff + i) = data; + Memory::Write32(address + i, data); i += 4; } else if (size == 2) { - *(u16*)(output_buff + i) = (u16)(data & 0xffff); + Memory::Write16(address + i, static_cast(data & 0xffff)); i += 2; } else { - *(u8*)(output_buff + i) = (u8)(data & 0xff); + Memory::Write8(address + i, static_cast(data & 0xff)); i++; } } From 99695d03d2ecce9bb6f8dbf23e763378b89b6759 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 19 Apr 2016 01:08:16 -0500 Subject: [PATCH 15/17] SOC_U: Remove usage of GetPointer --- src/core/hle/service/soc_u.cpp | 102 ++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 28 deletions(-) diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index d3e5d4bca5..a7404085b4 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp @@ -373,14 +373,18 @@ static void Bind(Service::Interface* self) { u32* cmd_buffer = Kernel::GetCommandBuffer(); u32 socket_handle = cmd_buffer[1]; u32 len = cmd_buffer[2]; - CTRSockAddr* ctr_sock_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[6])); - if (ctr_sock_addr == nullptr) { + // Virtual address of the sock_addr structure + VAddr sock_addr_addr = cmd_buffer[6]; + if (!Memory::IsValidVirtualAddress(sock_addr_addr)) { cmd_buffer[1] = -1; // TODO(Subv): Correct code return; } - sockaddr sock_addr = CTRSockAddr::ToPlatform(*ctr_sock_addr); + CTRSockAddr ctr_sock_addr; + Memory::ReadBlock(sock_addr_addr, reinterpret_cast(&ctr_sock_addr), sizeof(CTRSockAddr)); + + sockaddr sock_addr = CTRSockAddr::ToPlatform(ctr_sock_addr); int res = ::bind(socket_handle, &sock_addr, std::max(sizeof(sock_addr), len)); @@ -496,7 +500,7 @@ static void Accept(Service::Interface* self) { result = TranslateError(GET_ERRNO); } else { CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr); - Memory::WriteBlock(cmd_buffer[0x104 >> 2], (const u8*)&ctr_addr, max_addr_len); + Memory::WriteBlock(cmd_buffer[0x104 >> 2], &ctr_addr, sizeof(ctr_addr)); } cmd_buffer[0] = IPC::MakeHeader(4, 2, 2); @@ -547,20 +551,31 @@ static void SendTo(Service::Interface* self) { u32 flags = cmd_buffer[3]; u32 addr_len = cmd_buffer[4]; - u8* input_buff = Memory::GetPointer(cmd_buffer[8]); - CTRSockAddr* ctr_dest_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[10])); - - if (ctr_dest_addr == nullptr) { + VAddr input_buff_address = cmd_buffer[8]; + if (!Memory::IsValidVirtualAddress(input_buff_address)) { cmd_buffer[1] = -1; // TODO(Subv): Find the right error code return; } + // Memory address of the dest_addr structure + VAddr dest_addr_addr = cmd_buffer[10]; + if (!Memory::IsValidVirtualAddress(dest_addr_addr)) { + cmd_buffer[1] = -1; // TODO(Subv): Find the right error code + return; + } + + std::vector input_buff(len); + Memory::ReadBlock(input_buff_address, input_buff.data(), input_buff.size()); + + CTRSockAddr ctr_dest_addr; + Memory::ReadBlock(dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); + int ret = -1; if (addr_len > 0) { - sockaddr dest_addr = CTRSockAddr::ToPlatform(*ctr_dest_addr); - ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, &dest_addr, sizeof(dest_addr)); + sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr); + ret = ::sendto(socket_handle, reinterpret_cast(input_buff.data()), len, flags, &dest_addr, sizeof(dest_addr)); } else { - ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, nullptr, 0); + ret = ::sendto(socket_handle, reinterpret_cast(input_buff.data()), len, flags, nullptr, 0); } int result = 0; @@ -591,14 +606,24 @@ static void RecvFrom(Service::Interface* self) { std::memcpy(&buffer_parameters, &cmd_buffer[64], sizeof(buffer_parameters)); - u8* output_buff = Memory::GetPointer(buffer_parameters.output_buffer_addr); + if (!Memory::IsValidVirtualAddress(buffer_parameters.output_buffer_addr)) { + cmd_buffer[1] = -1; // TODO(Subv): Find the right error code + return; + } + + if (!Memory::IsValidVirtualAddress(buffer_parameters.output_src_address_buffer)) { + cmd_buffer[1] = -1; // TODO(Subv): Find the right error code + return; + } + + std::vector output_buff(len); sockaddr src_addr; socklen_t src_addr_len = sizeof(src_addr); - int ret = ::recvfrom(socket_handle, (char*)output_buff, len, flags, &src_addr, &src_addr_len); + int ret = ::recvfrom(socket_handle, reinterpret_cast(output_buff.data()), len, flags, &src_addr, &src_addr_len); if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { - CTRSockAddr* ctr_src_addr = reinterpret_cast(Memory::GetPointer(buffer_parameters.output_src_address_buffer)); - *ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); + CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); + Memory::WriteBlock(buffer_parameters.output_src_address_buffer, reinterpret_cast(&ctr_src_addr), sizeof(ctr_src_addr)); } int result = 0; @@ -606,6 +631,9 @@ static void RecvFrom(Service::Interface* self) { if (ret == SOCKET_ERROR_VALUE) { result = TranslateError(GET_ERRNO); total_received = 0; + } else { + // Write only the data we received to avoid overwriting parts of the buffer with zeros + Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(), total_received); } cmd_buffer[1] = result; @@ -617,18 +645,28 @@ static void Poll(Service::Interface* self) { u32* cmd_buffer = Kernel::GetCommandBuffer(); u32 nfds = cmd_buffer[1]; int timeout = cmd_buffer[2]; - CTRPollFD* input_fds = reinterpret_cast(Memory::GetPointer(cmd_buffer[6])); - CTRPollFD* output_fds = reinterpret_cast(Memory::GetPointer(cmd_buffer[0x104 >> 2])); + + VAddr input_fds_addr = cmd_buffer[6]; + VAddr output_fds_addr = cmd_buffer[0x104 >> 2]; + if (!Memory::IsValidVirtualAddress(input_fds_addr) || !Memory::IsValidVirtualAddress(output_fds_addr)) { + cmd_buffer[1] = -1; // TODO(Subv): Find correct error code. + return; + } + + std::vector ctr_fds(nfds); + Memory::ReadBlock(input_fds_addr, reinterpret_cast(ctr_fds.data()), nfds * sizeof(CTRPollFD)); // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) // so we have to copy the data std::vector platform_pollfd(nfds); - std::transform(input_fds, input_fds + nfds, platform_pollfd.begin(), CTRPollFD::ToPlatform); + std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform); const int ret = ::poll(platform_pollfd.data(), nfds, timeout); // Now update the output pollfd structure - std::transform(platform_pollfd.begin(), platform_pollfd.end(), output_fds, CTRPollFD::FromPlatform); + std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform); + + Memory::WriteBlock(output_fds_addr, reinterpret_cast(ctr_fds.data()), nfds * sizeof(CTRPollFD)); int result = 0; if (ret == SOCKET_ERROR_VALUE) @@ -643,14 +681,16 @@ static void GetSockName(Service::Interface* self) { u32 socket_handle = cmd_buffer[1]; socklen_t ctr_len = cmd_buffer[2]; - CTRSockAddr* ctr_dest_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[0x104 >> 2])); + // Memory address of the ctr_dest_addr structure + VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; sockaddr dest_addr; socklen_t dest_addr_len = sizeof(dest_addr); int ret = ::getsockname(socket_handle, &dest_addr, &dest_addr_len); - if (ctr_dest_addr != nullptr) { - *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); + if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { + CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); + Memory::WriteBlock(ctr_dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); } else { cmd_buffer[1] = -1; // TODO(Subv): Verify error return; @@ -682,14 +722,16 @@ static void GetPeerName(Service::Interface* self) { u32 socket_handle = cmd_buffer[1]; socklen_t len = cmd_buffer[2]; - CTRSockAddr* ctr_dest_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[0x104 >> 2])); + // Memory address of the ctr_dest_addr structure + VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; sockaddr dest_addr; socklen_t dest_addr_len = sizeof(dest_addr); int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len); - if (ctr_dest_addr != nullptr) { - *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); + if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { + CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); + Memory::WriteBlock(ctr_dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); } else { cmd_buffer[1] = -1; return; @@ -711,13 +753,17 @@ static void Connect(Service::Interface* self) { u32 socket_handle = cmd_buffer[1]; socklen_t len = cmd_buffer[2]; - CTRSockAddr* ctr_input_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[6])); - if (ctr_input_addr == nullptr) { + // Memory address of the ctr_input_addr structure + VAddr ctr_input_addr_addr = cmd_buffer[6]; + if (!Memory::IsValidVirtualAddress(ctr_input_addr_addr)) { cmd_buffer[1] = -1; // TODO(Subv): Verify error return; } - sockaddr input_addr = CTRSockAddr::ToPlatform(*ctr_input_addr); + CTRSockAddr ctr_input_addr; + Memory::ReadBlock(ctr_input_addr_addr, reinterpret_cast(&ctr_input_addr), sizeof(ctr_input_addr)); + + sockaddr input_addr = CTRSockAddr::ToPlatform(ctr_input_addr); int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr)); int result = 0; if (ret != 0) From 660499ac01b9244301a0642f4a0209ef8309ace4 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 19 Apr 2016 14:08:02 -0500 Subject: [PATCH 16/17] Memory: Make ReadBlock and WriteBlock accept void pointers. --- src/core/hle/service/frd/frd.cpp | 10 ++++------ src/core/hle/service/soc_u.cpp | 14 +++++++------- src/core/memory.cpp | 8 ++++---- src/core/memory.h | 4 ++-- src/core/mmio.h | 4 ++-- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp index 15d604bb6c..29d1443652 100644 --- a/src/core/hle/service/frd/frd.cpp +++ b/src/core/hle/service/frd/frd.cpp @@ -23,7 +23,7 @@ void GetMyPresence(Service::Interface* self) { ASSERT(shifted_out_size == ((sizeof(MyPresence) << 14) | 2)); - Memory::WriteBlock(my_presence_addr, reinterpret_cast(&my_presence), sizeof(MyPresence)); + Memory::WriteBlock(my_presence_addr, &my_presence, sizeof(MyPresence)); cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -39,8 +39,7 @@ void GetFriendKeyList(Service::Interface* self) { FriendKey zero_key = {}; for (u32 i = 0; i < frd_count; ++i) { - Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), - reinterpret_cast(&zero_key), sizeof(FriendKey)); + Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), &zero_key, sizeof(FriendKey)); } cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -58,8 +57,7 @@ void GetFriendProfile(Service::Interface* self) { Profile zero_profile = {}; for (u32 i = 0; i < count; ++i) { - Memory::WriteBlock(profiles_addr + i * sizeof(Profile), - reinterpret_cast(&zero_profile), sizeof(Profile)); + Memory::WriteBlock(profiles_addr + i * sizeof(Profile), &zero_profile, sizeof(Profile)); } cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -88,7 +86,7 @@ void GetMyFriendKey(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = RESULT_SUCCESS.raw; // No error - Memory::WriteBlock(cmd_buff[2], reinterpret_cast(&my_friend_key), sizeof(FriendKey)); + Memory::WriteBlock(cmd_buff[2], &my_friend_key, sizeof(FriendKey)); LOG_WARNING(Service_FRD, "(STUBBED) called"); } diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index a7404085b4..9b285567b2 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp @@ -568,7 +568,7 @@ static void SendTo(Service::Interface* self) { Memory::ReadBlock(input_buff_address, input_buff.data(), input_buff.size()); CTRSockAddr ctr_dest_addr; - Memory::ReadBlock(dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); + Memory::ReadBlock(dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); int ret = -1; if (addr_len > 0) { @@ -623,7 +623,7 @@ static void RecvFrom(Service::Interface* self) { if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); - Memory::WriteBlock(buffer_parameters.output_src_address_buffer, reinterpret_cast(&ctr_src_addr), sizeof(ctr_src_addr)); + Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, sizeof(ctr_src_addr)); } int result = 0; @@ -654,7 +654,7 @@ static void Poll(Service::Interface* self) { } std::vector ctr_fds(nfds); - Memory::ReadBlock(input_fds_addr, reinterpret_cast(ctr_fds.data()), nfds * sizeof(CTRPollFD)); + Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) // so we have to copy the data @@ -666,7 +666,7 @@ static void Poll(Service::Interface* self) { // Now update the output pollfd structure std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform); - Memory::WriteBlock(output_fds_addr, reinterpret_cast(ctr_fds.data()), nfds * sizeof(CTRPollFD)); + Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); int result = 0; if (ret == SOCKET_ERROR_VALUE) @@ -690,7 +690,7 @@ static void GetSockName(Service::Interface* self) { if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); - Memory::WriteBlock(ctr_dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); + Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); } else { cmd_buffer[1] = -1; // TODO(Subv): Verify error return; @@ -731,7 +731,7 @@ static void GetPeerName(Service::Interface* self) { if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); - Memory::WriteBlock(ctr_dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); + Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); } else { cmd_buffer[1] = -1; return; @@ -761,7 +761,7 @@ static void Connect(Service::Interface* self) { } CTRSockAddr ctr_input_addr; - Memory::ReadBlock(ctr_input_addr_addr, reinterpret_cast(&ctr_input_addr), sizeof(ctr_input_addr)); + Memory::ReadBlock(ctr_input_addr_addr, &ctr_input_addr, sizeof(ctr_input_addr)); sockaddr input_addr = CTRSockAddr::ToPlatform(ctr_input_addr); int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr)); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index bf2493270d..2ac3e7de41 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -364,7 +364,7 @@ u64 Read64(const VAddr addr) { return Read(addr); } -void ReadBlock(const VAddr src_addr, u8* dest_buffer, const size_t size) { +void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { size_t remaining_size = size; size_t page_index = src_addr >> PAGE_BITS; size_t page_offset = src_addr & PAGE_MASK; @@ -398,7 +398,7 @@ void ReadBlock(const VAddr src_addr, u8* dest_buffer, const size_t size) { page_index++; page_offset = 0; - dest_buffer += copy_amount; + dest_buffer = static_cast(dest_buffer) + copy_amount; remaining_size -= copy_amount; } } @@ -419,7 +419,7 @@ void Write64(const VAddr addr, const u64 data) { Write(addr, data); } -void WriteBlock(const VAddr dest_addr, const u8* src_buffer, const size_t size) { +void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size) { size_t remaining_size = size; size_t page_index = dest_addr >> PAGE_BITS; size_t page_offset = dest_addr & PAGE_MASK; @@ -452,7 +452,7 @@ void WriteBlock(const VAddr dest_addr, const u8* src_buffer, const size_t size) page_index++; page_offset = 0; - src_buffer += copy_amount; + src_buffer = static_cast(src_buffer) + copy_amount; remaining_size -= copy_amount; } } diff --git a/src/core/memory.h b/src/core/memory.h index bb5dd0d153..ae5588dee9 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -123,8 +123,8 @@ void Write16(VAddr addr, u16 data); void Write32(VAddr addr, u32 data); void Write64(VAddr addr, u64 data); -void ReadBlock(const VAddr src_addr, u8* dest_buffer, size_t size); -void WriteBlock(const VAddr dest_addr, const u8* src_buffer, size_t size); +void ReadBlock(const VAddr src_addr, void* dest_buffer, size_t size); +void WriteBlock(const VAddr dest_addr, const void* src_buffer, size_t size); void ZeroBlock(const VAddr dest_addr, const size_t size); void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size); diff --git a/src/core/mmio.h b/src/core/mmio.h index 35b73b061c..d76f005d8c 100644 --- a/src/core/mmio.h +++ b/src/core/mmio.h @@ -25,14 +25,14 @@ public: virtual u32 Read32(VAddr addr) = 0; virtual u64 Read64(VAddr addr) = 0; - virtual bool ReadBlock(VAddr src_addr, u8* dest_buffer, size_t size) = 0; + virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, size_t size) = 0; virtual void Write8(VAddr addr, u8 data) = 0; virtual void Write16(VAddr addr, u16 data) = 0; virtual void Write32(VAddr addr, u32 data) = 0; virtual void Write64(VAddr addr, u64 data) = 0; - virtual bool WriteBlock(VAddr dest_addr, const u8* src_buffer, size_t size) = 0; + virtual bool WriteBlock(VAddr dest_addr, const void* src_buffer, size_t size) = 0; }; using MMIORegionPointer = std::shared_ptr; From 0aef634a54f786c49241c24b8d0c7aa3555b0fa1 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 15 May 2016 12:43:52 -0500 Subject: [PATCH 17/17] Memory: Handle RasterizerCachedMemory and RasterizerCachedSpecial page types in the memory block manipulation functions. --- src/core/hle/service/fs/archive.cpp | 1 - src/core/memory.cpp | 61 ++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index a7ebfde254..81b9abe4cc 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -116,7 +116,6 @@ ResultVal File::SyncRequest() { } Memory::WriteBlock(address, data.data(), *read); cmd_buff[2] = static_cast(*read); - Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(address), length); break; } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 2ac3e7de41..8c9e5d46dd 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -392,6 +392,20 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); break; } + case PageType::RasterizerCachedMemory: { + RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount); + break; + } + case PageType::RasterizerCachedSpecial: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); + break; + } default: UNREACHABLE(); } @@ -446,6 +460,20 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); break; } + case PageType::RasterizerCachedMemory: { + RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); + break; + } + case PageType::RasterizerCachedSpecial: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); + break; + } default: UNREACHABLE(); } @@ -462,6 +490,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { size_t page_index = dest_addr >> PAGE_BITS; size_t page_offset = dest_addr & PAGE_MASK; + static const std::array zeros = {}; + while (remaining_size > 0) { const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; @@ -481,7 +511,20 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { case PageType::Special: { DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); - static const std::array zeros = {}; + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); + break; + } + case PageType::RasterizerCachedMemory: { + RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); + break; + } + case PageType::RasterizerCachedSpecial: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); break; } @@ -524,6 +567,22 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { WriteBlock(dest_addr, buffer.data(), buffer.size()); break; } + case PageType::RasterizerCachedMemory: { + RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount); + break; + } + case PageType::RasterizerCachedSpecial: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + std::vector buffer(copy_amount); + GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); + WriteBlock(dest_addr, buffer.data(), buffer.size()); + break; + } default: UNREACHABLE(); }