diff options
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 18 | ||||
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 4 | ||||
| -rw-r--r-- | src/core/memory.cpp | 51 | ||||
| -rw-r--r-- | src/core/memory.h | 24 |
6 files changed, 70 insertions, 39 deletions
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 54ed680db..78e44f3bd 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -969,7 +969,8 @@ static void ReadMemory() { | |||
| 969 | SendReply("E01"); | 969 | SendReply("E01"); |
| 970 | } | 970 | } |
| 971 | 971 | ||
| 972 | if (!Memory::IsValidVirtualAddress(addr)) { | 972 | const auto& memory = Core::System::GetInstance().Memory(); |
| 973 | if (!memory.IsValidVirtualAddress(addr)) { | ||
| 973 | return SendReply("E00"); | 974 | return SendReply("E00"); |
| 974 | } | 975 | } |
| 975 | 976 | ||
| @@ -984,22 +985,23 @@ static void ReadMemory() { | |||
| 984 | /// Modify location in memory with data received from the gdb client. | 985 | /// Modify location in memory with data received from the gdb client. |
| 985 | static void WriteMemory() { | 986 | static void WriteMemory() { |
| 986 | auto start_offset = command_buffer + 1; | 987 | auto start_offset = command_buffer + 1; |
| 987 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); | 988 | const auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 988 | VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); | 989 | const VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); |
| 989 | 990 | ||
| 990 | start_offset = addr_pos + 1; | 991 | start_offset = addr_pos + 1; |
| 991 | auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); | 992 | const auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); |
| 992 | u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset)); | 993 | const u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset)); |
| 993 | 994 | ||
| 994 | if (!Memory::IsValidVirtualAddress(addr)) { | 995 | auto& system = Core::System::GetInstance(); |
| 996 | const auto& memory = system.Memory(); | ||
| 997 | if (!memory.IsValidVirtualAddress(addr)) { | ||
| 995 | return SendReply("E00"); | 998 | return SendReply("E00"); |
| 996 | } | 999 | } |
| 997 | 1000 | ||
| 998 | std::vector<u8> data(len); | 1001 | std::vector<u8> data(len); |
| 999 | |||
| 1000 | GdbHexToMem(data.data(), len_pos + 1, len); | 1002 | GdbHexToMem(data.data(), len_pos + 1, len); |
| 1001 | Memory::WriteBlock(addr, data.data(), len); | 1003 | Memory::WriteBlock(addr, data.data(), len); |
| 1002 | Core::System::GetInstance().InvalidateCpuInstructionCaches(); | 1004 | system.InvalidateCpuInstructionCaches(); |
| 1003 | SendReply("OK"); | 1005 | SendReply("OK"); |
| 1004 | } | 1006 | } |
| 1005 | 1007 | ||
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 4859954cb..7f9a559d2 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -68,7 +68,7 @@ ResultCode AddressArbiter::SignalToAddressOnly(VAddr address, s32 num_to_wake) { | |||
| 68 | ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, | 68 | ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, |
| 69 | s32 num_to_wake) { | 69 | s32 num_to_wake) { |
| 70 | // Ensure that we can write to the address. | 70 | // Ensure that we can write to the address. |
| 71 | if (!Memory::IsValidVirtualAddress(address)) { | 71 | if (!system.Memory().IsValidVirtualAddress(address)) { |
| 72 | return ERR_INVALID_ADDRESS_STATE; | 72 | return ERR_INVALID_ADDRESS_STATE; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| @@ -83,7 +83,7 @@ ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 | |||
| 83 | ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, | 83 | ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, |
| 84 | s32 num_to_wake) { | 84 | s32 num_to_wake) { |
| 85 | // Ensure that we can write to the address. | 85 | // Ensure that we can write to the address. |
| 86 | if (!Memory::IsValidVirtualAddress(address)) { | 86 | if (!system.Memory().IsValidVirtualAddress(address)) { |
| 87 | return ERR_INVALID_ADDRESS_STATE; | 87 | return ERR_INVALID_ADDRESS_STATE; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| @@ -135,7 +135,7 @@ ResultCode AddressArbiter::WaitForAddress(VAddr address, ArbitrationType type, s | |||
| 135 | ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, | 135 | ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, |
| 136 | bool should_decrement) { | 136 | bool should_decrement) { |
| 137 | // Ensure that we can read the address. | 137 | // Ensure that we can read the address. |
| 138 | if (!Memory::IsValidVirtualAddress(address)) { | 138 | if (!system.Memory().IsValidVirtualAddress(address)) { |
| 139 | return ERR_INVALID_ADDRESS_STATE; | 139 | return ERR_INVALID_ADDRESS_STATE; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| @@ -158,7 +158,7 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6 | |||
| 158 | 158 | ||
| 159 | ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { | 159 | ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { |
| 160 | // Ensure that we can read the address. | 160 | // Ensure that we can read the address. |
| 161 | if (!Memory::IsValidVirtualAddress(address)) { | 161 | if (!system.Memory().IsValidVirtualAddress(address)) { |
| 162 | return ERR_INVALID_ADDRESS_STATE; | 162 | return ERR_INVALID_ADDRESS_STATE; |
| 163 | } | 163 | } |
| 164 | // Only wait for the address if equal. | 164 | // Only wait for the address if equal. |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 9928b3a26..eddafaf60 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -332,7 +332,7 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad | |||
| 332 | /// Connect to an OS service given the port name, returns the handle to the port to out | 332 | /// Connect to an OS service given the port name, returns the handle to the port to out |
| 333 | static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, | 333 | static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, |
| 334 | VAddr port_name_address) { | 334 | VAddr port_name_address) { |
| 335 | if (!Memory::IsValidVirtualAddress(port_name_address)) { | 335 | if (!system.Memory().IsValidVirtualAddress(port_name_address)) { |
| 336 | LOG_ERROR(Kernel_SVC, | 336 | LOG_ERROR(Kernel_SVC, |
| 337 | "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}", | 337 | "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}", |
| 338 | port_name_address); | 338 | port_name_address); |
| @@ -452,7 +452,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr | |||
| 452 | LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, handle_count={}, nano_seconds={}", | 452 | LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, handle_count={}, nano_seconds={}", |
| 453 | handles_address, handle_count, nano_seconds); | 453 | handles_address, handle_count, nano_seconds); |
| 454 | 454 | ||
| 455 | if (!Memory::IsValidVirtualAddress(handles_address)) { | 455 | if (!system.Memory().IsValidVirtualAddress(handles_address)) { |
| 456 | LOG_ERROR(Kernel_SVC, | 456 | LOG_ERROR(Kernel_SVC, |
| 457 | "Handle address is not a valid virtual address, handle_address=0x{:016X}", | 457 | "Handle address is not a valid virtual address, handle_address=0x{:016X}", |
| 458 | handles_address); | 458 | handles_address); |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 735019d96..e84e5ce0d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -162,13 +162,13 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin | |||
| 162 | return ERR_INVALID_PROCESSOR_ID; | 162 | return ERR_INVALID_PROCESSOR_ID; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | if (!Memory::IsValidVirtualAddress(owner_process, entry_point)) { | 165 | auto& system = Core::System::GetInstance(); |
| 166 | if (!system.Memory().IsValidVirtualAddress(owner_process, entry_point)) { | ||
| 166 | LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point); | 167 | LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point); |
| 167 | // TODO (bunnei): Find the correct error code to use here | 168 | // TODO (bunnei): Find the correct error code to use here |
| 168 | return RESULT_UNKNOWN; | 169 | return RESULT_UNKNOWN; |
| 169 | } | 170 | } |
| 170 | 171 | ||
| 171 | auto& system = Core::System::GetInstance(); | ||
| 172 | std::shared_ptr<Thread> thread = std::make_shared<Thread>(kernel); | 172 | std::shared_ptr<Thread> thread = std::make_shared<Thread>(kernel); |
| 173 | 173 | ||
| 174 | thread->thread_id = kernel.CreateNewThreadID(); | 174 | thread->thread_id = kernel.CreateNewThreadID(); |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 28b65ca5e..4c13ea1e7 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -75,6 +75,29 @@ struct Memory::Impl { | |||
| 75 | std::make_pair(interval, std::set<Common::SpecialRegion>{region})); | 75 | std::make_pair(interval, std::set<Common::SpecialRegion>{region})); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const { | ||
| 79 | const auto& page_table = process.VMManager().page_table; | ||
| 80 | |||
| 81 | const u8* const page_pointer = page_table.pointers[vaddr >> PAGE_BITS]; | ||
| 82 | if (page_pointer != nullptr) { | ||
| 83 | return true; | ||
| 84 | } | ||
| 85 | |||
| 86 | if (page_table.attributes[vaddr >> PAGE_BITS] == Common::PageType::RasterizerCachedMemory) { | ||
| 87 | return true; | ||
| 88 | } | ||
| 89 | |||
| 90 | if (page_table.attributes[vaddr >> PAGE_BITS] != Common::PageType::Special) { | ||
| 91 | return false; | ||
| 92 | } | ||
| 93 | |||
| 94 | return false; | ||
| 95 | } | ||
| 96 | |||
| 97 | bool IsValidVirtualAddress(VAddr vaddr) const { | ||
| 98 | return IsValidVirtualAddress(*system.CurrentProcess(), vaddr); | ||
| 99 | } | ||
| 100 | |||
| 78 | /** | 101 | /** |
| 79 | * Maps a region of pages as a specific type. | 102 | * Maps a region of pages as a specific type. |
| 80 | * | 103 | * |
| @@ -148,6 +171,14 @@ void Memory::RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size | |||
| 148 | impl->RemoveDebugHook(page_table, base, size, std::move(hook)); | 171 | impl->RemoveDebugHook(page_table, base, size, std::move(hook)); |
| 149 | } | 172 | } |
| 150 | 173 | ||
| 174 | bool Memory::IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const { | ||
| 175 | return impl->IsValidVirtualAddress(process, vaddr); | ||
| 176 | } | ||
| 177 | |||
| 178 | bool Memory::IsValidVirtualAddress(const VAddr vaddr) const { | ||
| 179 | return impl->IsValidVirtualAddress(vaddr); | ||
| 180 | } | ||
| 181 | |||
| 151 | void SetCurrentPageTable(Kernel::Process& process) { | 182 | void SetCurrentPageTable(Kernel::Process& process) { |
| 152 | current_page_table = &process.VMManager().page_table; | 183 | current_page_table = &process.VMManager().page_table; |
| 153 | 184 | ||
| @@ -256,26 +287,6 @@ void Write(const VAddr vaddr, const T data) { | |||
| 256 | } | 287 | } |
| 257 | } | 288 | } |
| 258 | 289 | ||
| 259 | bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) { | ||
| 260 | const auto& page_table = process.VMManager().page_table; | ||
| 261 | |||
| 262 | const u8* page_pointer = page_table.pointers[vaddr >> PAGE_BITS]; | ||
| 263 | if (page_pointer) | ||
| 264 | return true; | ||
| 265 | |||
| 266 | if (page_table.attributes[vaddr >> PAGE_BITS] == Common::PageType::RasterizerCachedMemory) | ||
| 267 | return true; | ||
| 268 | |||
| 269 | if (page_table.attributes[vaddr >> PAGE_BITS] != Common::PageType::Special) | ||
| 270 | return false; | ||
| 271 | |||
| 272 | return false; | ||
| 273 | } | ||
| 274 | |||
| 275 | bool IsValidVirtualAddress(const VAddr vaddr) { | ||
| 276 | return IsValidVirtualAddress(*Core::System::GetInstance().CurrentProcess(), vaddr); | ||
| 277 | } | ||
| 278 | |||
| 279 | bool IsKernelVirtualAddress(const VAddr vaddr) { | 290 | bool IsKernelVirtualAddress(const VAddr vaddr) { |
| 280 | return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; | 291 | return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; |
| 281 | } | 292 | } |
diff --git a/src/core/memory.h b/src/core/memory.h index 87ed3b696..cacf4fb1a 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -111,6 +111,27 @@ public: | |||
| 111 | void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size, | 111 | void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size, |
| 112 | Common::MemoryHookPointer hook); | 112 | Common::MemoryHookPointer hook); |
| 113 | 113 | ||
| 114 | /** | ||
| 115 | * Checks whether or not the supplied address is a valid virtual | ||
| 116 | * address for the given process. | ||
| 117 | * | ||
| 118 | * @param process The emulated process to check the address against. | ||
| 119 | * @param vaddr The virtual address to check the validity of. | ||
| 120 | * | ||
| 121 | * @returns True if the given virtual address is valid, false otherwise. | ||
| 122 | */ | ||
| 123 | bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr) const; | ||
| 124 | |||
| 125 | /** | ||
| 126 | * Checks whether or not the supplied address is a valid virtual | ||
| 127 | * address for the current process. | ||
| 128 | * | ||
| 129 | * @param vaddr The virtual address to check the validity of. | ||
| 130 | * | ||
| 131 | * @returns True if the given virtual address is valid, false otherwise. | ||
| 132 | */ | ||
| 133 | bool IsValidVirtualAddress(VAddr vaddr) const; | ||
| 134 | |||
| 114 | private: | 135 | private: |
| 115 | struct Impl; | 136 | struct Impl; |
| 116 | std::unique_ptr<Impl> impl; | 137 | std::unique_ptr<Impl> impl; |
| @@ -120,9 +141,6 @@ private: | |||
| 120 | /// the given process instance. | 141 | /// the given process instance. |
| 121 | void SetCurrentPageTable(Kernel::Process& process); | 142 | void SetCurrentPageTable(Kernel::Process& process); |
| 122 | 143 | ||
| 123 | /// Determines if the given VAddr is valid for the specified process. | ||
| 124 | bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr); | ||
| 125 | bool IsValidVirtualAddress(VAddr vaddr); | ||
| 126 | /// Determines if the given VAddr is a kernel address | 144 | /// Determines if the given VAddr is a kernel address |
| 127 | bool IsKernelVirtualAddress(VAddr vaddr); | 145 | bool IsKernelVirtualAddress(VAddr vaddr); |
| 128 | 146 | ||