diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/memory.cpp | 199 | ||||
| -rw-r--r-- | src/core/memory.h | 53 |
2 files changed, 161 insertions, 91 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 8c3489ed3..c939e980d 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -225,6 +225,99 @@ struct Memory::Impl { | |||
| 225 | return string; | 225 | return string; |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { | ||
| 229 | const auto& page_table = process.VMManager().page_table; | ||
| 230 | std::size_t remaining_size = size; | ||
| 231 | std::size_t page_index = dest_addr >> PAGE_BITS; | ||
| 232 | std::size_t page_offset = dest_addr & PAGE_MASK; | ||
| 233 | |||
| 234 | while (remaining_size > 0) { | ||
| 235 | const std::size_t copy_amount = | ||
| 236 | std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size); | ||
| 237 | const auto current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); | ||
| 238 | |||
| 239 | switch (page_table.attributes[page_index]) { | ||
| 240 | case Common::PageType::Unmapped: { | ||
| 241 | LOG_ERROR(HW_Memory, | ||
| 242 | "Unmapped ZeroBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 243 | current_vaddr, dest_addr, size); | ||
| 244 | break; | ||
| 245 | } | ||
| 246 | case Common::PageType::Memory: { | ||
| 247 | DEBUG_ASSERT(page_table.pointers[page_index]); | ||
| 248 | |||
| 249 | u8* dest_ptr = page_table.pointers[page_index] + page_offset; | ||
| 250 | std::memset(dest_ptr, 0, copy_amount); | ||
| 251 | break; | ||
| 252 | } | ||
| 253 | case Common::PageType::RasterizerCachedMemory: { | ||
| 254 | u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); | ||
| 255 | system.GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount); | ||
| 256 | std::memset(host_ptr, 0, copy_amount); | ||
| 257 | break; | ||
| 258 | } | ||
| 259 | default: | ||
| 260 | UNREACHABLE(); | ||
| 261 | } | ||
| 262 | |||
| 263 | page_index++; | ||
| 264 | page_offset = 0; | ||
| 265 | remaining_size -= copy_amount; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | void ZeroBlock(const VAddr dest_addr, const std::size_t size) { | ||
| 270 | ZeroBlock(*system.CurrentProcess(), dest_addr, size); | ||
| 271 | } | ||
| 272 | |||
| 273 | void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | ||
| 274 | const std::size_t size) { | ||
| 275 | const auto& page_table = process.VMManager().page_table; | ||
| 276 | std::size_t remaining_size = size; | ||
| 277 | std::size_t page_index = src_addr >> PAGE_BITS; | ||
| 278 | std::size_t page_offset = src_addr & PAGE_MASK; | ||
| 279 | |||
| 280 | while (remaining_size > 0) { | ||
| 281 | const std::size_t copy_amount = | ||
| 282 | std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size); | ||
| 283 | const auto current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); | ||
| 284 | |||
| 285 | switch (page_table.attributes[page_index]) { | ||
| 286 | case Common::PageType::Unmapped: { | ||
| 287 | LOG_ERROR(HW_Memory, | ||
| 288 | "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 289 | current_vaddr, src_addr, size); | ||
| 290 | ZeroBlock(process, dest_addr, copy_amount); | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | case Common::PageType::Memory: { | ||
| 294 | DEBUG_ASSERT(page_table.pointers[page_index]); | ||
| 295 | const u8* src_ptr = page_table.pointers[page_index] + page_offset; | ||
| 296 | WriteBlock(process, dest_addr, src_ptr, copy_amount); | ||
| 297 | break; | ||
| 298 | } | ||
| 299 | case Common::PageType::RasterizerCachedMemory: { | ||
| 300 | const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); | ||
| 301 | system.GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount); | ||
| 302 | WriteBlock(process, dest_addr, host_ptr, copy_amount); | ||
| 303 | break; | ||
| 304 | } | ||
| 305 | default: | ||
| 306 | UNREACHABLE(); | ||
| 307 | } | ||
| 308 | |||
| 309 | page_index++; | ||
| 310 | page_offset = 0; | ||
| 311 | dest_addr += static_cast<VAddr>(copy_amount); | ||
| 312 | src_addr += static_cast<VAddr>(copy_amount); | ||
| 313 | remaining_size -= copy_amount; | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 317 | void CopyBlock(VAddr dest_addr, VAddr src_addr, std::size_t size) { | ||
| 318 | return CopyBlock(*system.CurrentProcess(), dest_addr, src_addr, size); | ||
| 319 | } | ||
| 320 | |||
| 228 | void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { | 321 | void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { |
| 229 | if (vaddr == 0) { | 322 | if (vaddr == 0) { |
| 230 | return; | 323 | return; |
| @@ -381,6 +474,23 @@ std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) { | |||
| 381 | return impl->ReadCString(vaddr, max_length); | 474 | return impl->ReadCString(vaddr, max_length); |
| 382 | } | 475 | } |
| 383 | 476 | ||
| 477 | void Memory::ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size) { | ||
| 478 | impl->ZeroBlock(process, dest_addr, size); | ||
| 479 | } | ||
| 480 | |||
| 481 | void Memory::ZeroBlock(VAddr dest_addr, std::size_t size) { | ||
| 482 | impl->ZeroBlock(dest_addr, size); | ||
| 483 | } | ||
| 484 | |||
| 485 | void Memory::CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | ||
| 486 | const std::size_t size) { | ||
| 487 | impl->CopyBlock(process, dest_addr, src_addr, size); | ||
| 488 | } | ||
| 489 | |||
| 490 | void Memory::CopyBlock(VAddr dest_addr, VAddr src_addr, std::size_t size) { | ||
| 491 | impl->CopyBlock(dest_addr, src_addr, size); | ||
| 492 | } | ||
| 493 | |||
| 384 | void Memory::RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { | 494 | void Memory::RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { |
| 385 | impl->RasterizerMarkRegionCached(vaddr, size, cached); | 495 | impl->RasterizerMarkRegionCached(vaddr, size, cached); |
| 386 | } | 496 | } |
| @@ -529,93 +639,4 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t | |||
| 529 | WriteBlock(*Core::System::GetInstance().CurrentProcess(), dest_addr, src_buffer, size); | 639 | WriteBlock(*Core::System::GetInstance().CurrentProcess(), dest_addr, src_buffer, size); |
| 530 | } | 640 | } |
| 531 | 641 | ||
| 532 | void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { | ||
| 533 | const auto& page_table = process.VMManager().page_table; | ||
| 534 | std::size_t remaining_size = size; | ||
| 535 | std::size_t page_index = dest_addr >> PAGE_BITS; | ||
| 536 | std::size_t page_offset = dest_addr & PAGE_MASK; | ||
| 537 | |||
| 538 | while (remaining_size > 0) { | ||
| 539 | const std::size_t copy_amount = | ||
| 540 | std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size); | ||
| 541 | const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); | ||
| 542 | |||
| 543 | switch (page_table.attributes[page_index]) { | ||
| 544 | case Common::PageType::Unmapped: { | ||
| 545 | LOG_ERROR(HW_Memory, | ||
| 546 | "Unmapped ZeroBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 547 | current_vaddr, dest_addr, size); | ||
| 548 | break; | ||
| 549 | } | ||
| 550 | case Common::PageType::Memory: { | ||
| 551 | DEBUG_ASSERT(page_table.pointers[page_index]); | ||
| 552 | |||
| 553 | u8* dest_ptr = page_table.pointers[page_index] + page_offset; | ||
| 554 | std::memset(dest_ptr, 0, copy_amount); | ||
| 555 | break; | ||
| 556 | } | ||
| 557 | case Common::PageType::RasterizerCachedMemory: { | ||
| 558 | const auto& host_ptr{GetPointerFromVMA(process, current_vaddr)}; | ||
| 559 | Core::System::GetInstance().GPU().InvalidateRegion(ToCacheAddr(host_ptr), copy_amount); | ||
| 560 | std::memset(host_ptr, 0, copy_amount); | ||
| 561 | break; | ||
| 562 | } | ||
| 563 | default: | ||
| 564 | UNREACHABLE(); | ||
| 565 | } | ||
| 566 | |||
| 567 | page_index++; | ||
| 568 | page_offset = 0; | ||
| 569 | remaining_size -= copy_amount; | ||
| 570 | } | ||
| 571 | } | ||
| 572 | |||
| 573 | void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | ||
| 574 | const std::size_t size) { | ||
| 575 | const auto& page_table = process.VMManager().page_table; | ||
| 576 | std::size_t remaining_size = size; | ||
| 577 | std::size_t page_index = src_addr >> PAGE_BITS; | ||
| 578 | std::size_t page_offset = src_addr & PAGE_MASK; | ||
| 579 | |||
| 580 | while (remaining_size > 0) { | ||
| 581 | const std::size_t copy_amount = | ||
| 582 | std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size); | ||
| 583 | const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset); | ||
| 584 | |||
| 585 | switch (page_table.attributes[page_index]) { | ||
| 586 | case Common::PageType::Unmapped: { | ||
| 587 | LOG_ERROR(HW_Memory, | ||
| 588 | "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", | ||
| 589 | current_vaddr, src_addr, size); | ||
| 590 | ZeroBlock(process, dest_addr, copy_amount); | ||
| 591 | break; | ||
| 592 | } | ||
| 593 | case Common::PageType::Memory: { | ||
| 594 | DEBUG_ASSERT(page_table.pointers[page_index]); | ||
| 595 | const u8* src_ptr = page_table.pointers[page_index] + page_offset; | ||
| 596 | WriteBlock(process, dest_addr, src_ptr, copy_amount); | ||
| 597 | break; | ||
| 598 | } | ||
| 599 | case Common::PageType::RasterizerCachedMemory: { | ||
| 600 | const auto& host_ptr{GetPointerFromVMA(process, current_vaddr)}; | ||
| 601 | Core::System::GetInstance().GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount); | ||
| 602 | WriteBlock(process, dest_addr, host_ptr, copy_amount); | ||
| 603 | break; | ||
| 604 | } | ||
| 605 | default: | ||
| 606 | UNREACHABLE(); | ||
| 607 | } | ||
| 608 | |||
| 609 | page_index++; | ||
| 610 | page_offset = 0; | ||
| 611 | dest_addr += static_cast<VAddr>(copy_amount); | ||
| 612 | src_addr += static_cast<VAddr>(copy_amount); | ||
| 613 | remaining_size -= copy_amount; | ||
| 614 | } | ||
| 615 | } | ||
| 616 | |||
| 617 | void CopyBlock(VAddr dest_addr, VAddr src_addr, std::size_t size) { | ||
| 618 | CopyBlock(*Core::System::GetInstance().CurrentProcess(), dest_addr, src_addr, size); | ||
| 619 | } | ||
| 620 | |||
| 621 | } // namespace Memory | 642 | } // namespace Memory |
diff --git a/src/core/memory.h b/src/core/memory.h index 7cd348b49..fc0013a96 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -170,6 +170,57 @@ public: | |||
| 170 | std::string ReadCString(VAddr vaddr, std::size_t max_length); | 170 | std::string ReadCString(VAddr vaddr, std::size_t max_length); |
| 171 | 171 | ||
| 172 | /** | 172 | /** |
| 173 | * Fills the specified address range within a process' address space with zeroes. | ||
| 174 | * | ||
| 175 | * @param process The process that will have a portion of its memory zeroed out. | ||
| 176 | * @param dest_addr The starting virtual address of the range to zero out. | ||
| 177 | * @param size The size of the address range to zero out, in bytes. | ||
| 178 | * | ||
| 179 | * @post The range [dest_addr, size) within the process' address space is | ||
| 180 | * filled with zeroes. | ||
| 181 | */ | ||
| 182 | void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size); | ||
| 183 | |||
| 184 | /** | ||
| 185 | * Fills the specified address range within the current process' address space with zeroes. | ||
| 186 | * | ||
| 187 | * @param dest_addr The starting virtual address of the range to zero out. | ||
| 188 | * @param size The size of the address range to zero out, in bytes. | ||
| 189 | * | ||
| 190 | * @post The range [dest_addr, size) within the current process' address space is | ||
| 191 | * filled with zeroes. | ||
| 192 | */ | ||
| 193 | void ZeroBlock(VAddr dest_addr, std::size_t size); | ||
| 194 | |||
| 195 | /** | ||
| 196 | * Copies data within a process' address space to another location within the | ||
| 197 | * same address space. | ||
| 198 | * | ||
| 199 | * @param process The process that will have data copied within its address space. | ||
| 200 | * @param dest_addr The destination virtual address to begin copying the data into. | ||
| 201 | * @param src_addr The source virtual address to begin copying the data from. | ||
| 202 | * @param size The size of the data to copy, in bytes. | ||
| 203 | * | ||
| 204 | * @post The range [dest_addr, size) within the process' address space contains the | ||
| 205 | * same data within the range [src_addr, size). | ||
| 206 | */ | ||
| 207 | void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | ||
| 208 | std::size_t size); | ||
| 209 | |||
| 210 | /** | ||
| 211 | * Copies data within the current process' address space to another location within the | ||
| 212 | * same address space. | ||
| 213 | * | ||
| 214 | * @param dest_addr The destination virtual address to begin copying the data into. | ||
| 215 | * @param src_addr The source virtual address to begin copying the data from. | ||
| 216 | * @param size The size of the data to copy, in bytes. | ||
| 217 | * | ||
| 218 | * @post The range [dest_addr, size) within the current process' address space | ||
| 219 | * contains the same data within the range [src_addr, size). | ||
| 220 | */ | ||
| 221 | void CopyBlock(VAddr dest_addr, VAddr src_addr, std::size_t size); | ||
| 222 | |||
| 223 | /** | ||
| 173 | * Marks each page within the specified address range as cached or uncached. | 224 | * Marks each page within the specified address range as cached or uncached. |
| 174 | * | 225 | * |
| 175 | * @param vaddr The virtual address indicating the start of the address range. | 226 | * @param vaddr The virtual address indicating the start of the address range. |
| @@ -206,7 +257,5 @@ void ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size); | |||
| 206 | void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, | 257 | void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer, |
| 207 | std::size_t size); | 258 | std::size_t size); |
| 208 | void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size); | 259 | void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size); |
| 209 | void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size); | ||
| 210 | void CopyBlock(VAddr dest_addr, VAddr src_addr, std::size_t size); | ||
| 211 | 260 | ||
| 212 | } // namespace Memory | 261 | } // namespace Memory |