summaryrefslogtreecommitdiff
path: root/src/core/memory.cpp
diff options
context:
space:
mode:
authorGravatar David Marcec2018-04-26 14:28:54 -0700
committerGravatar David Marcec2018-04-26 14:28:54 -0700
commit7391741a204d6f25a06132eda214b2199b60a084 (patch)
treeaeeb723744c4563ad608361b82dd938b062a3e09 /src/core/memory.cpp
parentAdded PREPO to logging backend, Removed comments from SaveReportWithUser (diff)
parentMerge pull request #403 from lioncash/common (diff)
downloadyuzu-7391741a204d6f25a06132eda214b2199b60a084.tar.gz
yuzu-7391741a204d6f25a06132eda214b2199b60a084.tar.xz
yuzu-7391741a204d6f25a06132eda214b2199b60a084.zip
Merge branch 'master' of https://github.com/yuzu-emu/yuzu into service-impl
Diffstat (limited to 'src/core/memory.cpp')
-rw-r--r--src/core/memory.cpp112
1 files changed, 75 insertions, 37 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 291bf066f..2afa0916d 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -39,8 +39,8 @@ PageTable* GetCurrentPageTable() {
39} 39}
40 40
41static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) { 41static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) {
42 LOG_DEBUG(HW_Memory, "Mapping %p onto %016" PRIX64 "-%016" PRIX64, memory, base * PAGE_SIZE, 42 NGLOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE,
43 (base + size) * PAGE_SIZE); 43 (base + size) * PAGE_SIZE);
44 44
45 RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE, 45 RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE,
46 FlushMode::FlushAndInvalidate); 46 FlushMode::FlushAndInvalidate);
@@ -169,10 +169,10 @@ T Read(const VAddr vaddr) {
169 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; 169 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
170 switch (type) { 170 switch (type) {
171 case PageType::Unmapped: 171 case PageType::Unmapped:
172 LOG_ERROR(HW_Memory, "unmapped Read%lu @ 0x%08X", sizeof(T) * 8, vaddr); 172 NGLOG_ERROR(HW_Memory, "Unmapped Read{} @ {:#010X}", sizeof(T) * 8, vaddr);
173 return 0; 173 return 0;
174 case PageType::Memory: 174 case PageType::Memory:
175 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 175 ASSERT_MSG(false, "Mapped memory page without a pointer @ %016" PRIX64, vaddr);
176 break; 176 break;
177 case PageType::RasterizerCachedMemory: { 177 case PageType::RasterizerCachedMemory: {
178 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush); 178 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Flush);
@@ -201,11 +201,11 @@ void Write(const VAddr vaddr, const T data) {
201 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; 201 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
202 switch (type) { 202 switch (type) {
203 case PageType::Unmapped: 203 case PageType::Unmapped:
204 LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, 204 NGLOG_ERROR(HW_Memory, "Unmapped Write{} {:#010X} @ {:#018X}", sizeof(data) * 8, (u32)data,
205 vaddr); 205 vaddr);
206 return; 206 return;
207 case PageType::Memory: 207 case PageType::Memory:
208 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 208 ASSERT_MSG(false, "Mapped memory page without a pointer @ %016" PRIX64, vaddr);
209 break; 209 break;
210 case PageType::RasterizerCachedMemory: { 210 case PageType::RasterizerCachedMemory: {
211 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate); 211 RasterizerFlushVirtualRegion(vaddr, sizeof(T), FlushMode::Invalidate);
@@ -251,7 +251,7 @@ u8* GetPointer(const VAddr vaddr) {
251 return GetPointerFromVMA(vaddr); 251 return GetPointerFromVMA(vaddr);
252 } 252 }
253 253
254 LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr); 254 NGLOG_ERROR(HW_Memory, "Unknown GetPointer @ {:#018X}", vaddr);
255 return nullptr; 255 return nullptr;
256} 256}
257 257
@@ -288,13 +288,12 @@ u8* GetPhysicalPointer(PAddr address) {
288 }); 288 });
289 289
290 if (area == std::end(memory_areas)) { 290 if (area == std::end(memory_areas)) {
291 LOG_ERROR(HW_Memory, "unknown GetPhysicalPointer @ 0x%016" PRIX64, address); 291 NGLOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#018X}", address);
292 return nullptr; 292 return nullptr;
293 } 293 }
294 294
295 if (area->paddr_base == IO_AREA_PADDR) { 295 if (area->paddr_base == IO_AREA_PADDR) {
296 LOG_ERROR(HW_Memory, "MMIO mappings are not supported yet. phys_addr=0x%016" PRIX64, 296 NGLOG_ERROR(HW_Memory, "MMIO mappings are not supported yet. phys_addr={:018X}", address);
297 address);
298 return nullptr; 297 return nullptr;
299 } 298 }
300 299
@@ -325,15 +324,29 @@ u8* GetPhysicalPointer(PAddr address) {
325 return target_pointer; 324 return target_pointer;
326} 325}
327 326
328void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) { 327void RasterizerMarkRegionCached(Tegra::GPUVAddr gpu_addr, u64 size, bool cached) {
329 if (start == 0) { 328 if (gpu_addr == 0) {
330 return; 329 return;
331 } 330 }
332 331
333 u64 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1; 332 // Iterate over a contiguous CPU address space, which corresponds to the specified GPU address
334 VAddr vaddr = start; 333 // space, marking the region as un/cached. The region is marked un/cached at a granularity of
334 // CPU pages, hence why we iterate on a CPU page basis (note: GPU page size is different). This
335 // assumes the specified GPU address region is contiguous as well.
336
337 u64 num_pages = ((gpu_addr + size - 1) >> PAGE_BITS) - (gpu_addr >> PAGE_BITS) + 1;
338 for (unsigned i = 0; i < num_pages; ++i, gpu_addr += PAGE_SIZE) {
339 boost::optional<VAddr> maybe_vaddr =
340 Core::System::GetInstance().GPU().memory_manager->GpuToCpuAddress(gpu_addr);
341 // The GPU <-> CPU virtual memory mapping is not 1:1
342 if (!maybe_vaddr) {
343 NGLOG_ERROR(HW_Memory,
344 "Trying to flush a cached region to an invalid physical address {:016X}",
345 gpu_addr);
346 continue;
347 }
348 VAddr vaddr = *maybe_vaddr;
335 349
336 for (unsigned i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) {
337 PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; 350 PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
338 351
339 if (cached) { 352 if (cached) {
@@ -347,6 +360,10 @@ void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) {
347 page_type = PageType::RasterizerCachedMemory; 360 page_type = PageType::RasterizerCachedMemory;
348 current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr; 361 current_page_table->pointers[vaddr >> PAGE_BITS] = nullptr;
349 break; 362 break;
363 case PageType::RasterizerCachedMemory:
364 // There can be more than one GPU region mapped per CPU region, so it's common that
365 // this area is already marked as cached.
366 break;
350 default: 367 default:
351 UNREACHABLE(); 368 UNREACHABLE();
352 } 369 }
@@ -357,6 +374,10 @@ void RasterizerMarkRegionCached(VAddr start, u64 size, bool cached) {
357 // It is not necessary for a process to have this region mapped into its address 374 // It is not necessary for a process to have this region mapped into its address
358 // space, for example, a system module need not have a VRAM mapping. 375 // space, for example, a system module need not have a VRAM mapping.
359 break; 376 break;
377 case PageType::Memory:
378 // There can be more than one GPU region mapped per CPU region, so it's common that
379 // this area is already unmarked as cached.
380 break;
360 case PageType::RasterizerCachedMemory: { 381 case PageType::RasterizerCachedMemory: {
361 u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); 382 u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
362 if (pointer == nullptr) { 383 if (pointer == nullptr) {
@@ -394,19 +415,29 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) {
394 415
395 VAddr overlap_start = std::max(start, region_start); 416 VAddr overlap_start = std::max(start, region_start);
396 VAddr overlap_end = std::min(end, region_end); 417 VAddr overlap_end = std::min(end, region_end);
418
419 std::vector<Tegra::GPUVAddr> gpu_addresses =
420 Core::System::GetInstance().GPU().memory_manager->CpuToGpuAddress(overlap_start);
421
422 if (gpu_addresses.empty()) {
423 return;
424 }
425
397 u64 overlap_size = overlap_end - overlap_start; 426 u64 overlap_size = overlap_end - overlap_start;
398 427
399 auto* rasterizer = VideoCore::g_renderer->Rasterizer(); 428 for (const auto& gpu_address : gpu_addresses) {
400 switch (mode) { 429 auto* rasterizer = VideoCore::g_renderer->Rasterizer();
401 case FlushMode::Flush: 430 switch (mode) {
402 rasterizer->FlushRegion(overlap_start, overlap_size); 431 case FlushMode::Flush:
403 break; 432 rasterizer->FlushRegion(gpu_address, overlap_size);
404 case FlushMode::Invalidate: 433 break;
405 rasterizer->InvalidateRegion(overlap_start, overlap_size); 434 case FlushMode::Invalidate:
406 break; 435 rasterizer->InvalidateRegion(gpu_address, overlap_size);
407 case FlushMode::FlushAndInvalidate: 436 break;
408 rasterizer->FlushAndInvalidateRegion(overlap_start, overlap_size); 437 case FlushMode::FlushAndInvalidate:
409 break; 438 rasterizer->FlushAndInvalidateRegion(gpu_address, overlap_size);
439 break;
440 }
410 } 441 }
411 }; 442 };
412 443
@@ -445,8 +476,9 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_
445 476
446 switch (page_table.attributes[page_index]) { 477 switch (page_table.attributes[page_index]) {
447 case PageType::Unmapped: { 478 case PageType::Unmapped: {
448 LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", 479 NGLOG_ERROR(HW_Memory,
449 current_vaddr, src_addr, size); 480 "Unmapped ReadBlock @ {:#018X} (start address = {:#018X}, size = {})",
481 current_vaddr, src_addr, size);
450 std::memset(dest_buffer, 0, copy_amount); 482 std::memset(dest_buffer, 0, copy_amount);
451 break; 483 break;
452 } 484 }
@@ -508,9 +540,9 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi
508 540
509 switch (page_table.attributes[page_index]) { 541 switch (page_table.attributes[page_index]) {
510 case PageType::Unmapped: { 542 case PageType::Unmapped: {
511 LOG_ERROR(HW_Memory, 543 NGLOG_ERROR(HW_Memory,
512 "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", 544 "Unmapped WriteBlock @ {:#018X} (start address = {:#018X}, size = {})",
513 current_vaddr, dest_addr, size); 545 current_vaddr, dest_addr, size);
514 break; 546 break;
515 } 547 }
516 case PageType::Memory: { 548 case PageType::Memory: {
@@ -556,8 +588,9 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const size
556 588
557 switch (page_table.attributes[page_index]) { 589 switch (page_table.attributes[page_index]) {
558 case PageType::Unmapped: { 590 case PageType::Unmapped: {
559 LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", 591 NGLOG_ERROR(HW_Memory,
560 current_vaddr, dest_addr, size); 592 "Unmapped ZeroBlock @ {:#018X} (start address = {#:018X}, size = {})",
593 current_vaddr, dest_addr, size);
561 break; 594 break;
562 } 595 }
563 case PageType::Memory: { 596 case PageType::Memory: {
@@ -596,8 +629,9 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
596 629
597 switch (page_table.attributes[page_index]) { 630 switch (page_table.attributes[page_index]) {
598 case PageType::Unmapped: { 631 case PageType::Unmapped: {
599 LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", 632 NGLOG_ERROR(HW_Memory,
600 current_vaddr, src_addr, size); 633 "Unmapped CopyBlock @ {:#018X} (start address = {:#018X}, size = {})",
634 current_vaddr, src_addr, size);
601 ZeroBlock(process, dest_addr, copy_amount); 635 ZeroBlock(process, dest_addr, copy_amount);
602 break; 636 break;
603 } 637 }
@@ -625,6 +659,10 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
625 } 659 }
626} 660}
627 661
662void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size) {
663 CopyBlock(*Core::CurrentProcess(), dest_addr, src_addr, size);
664}
665
628boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) { 666boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) {
629 if (addr == 0) { 667 if (addr == 0) {
630 return 0; 668 return 0;
@@ -646,7 +684,7 @@ boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) {
646PAddr VirtualToPhysicalAddress(const VAddr addr) { 684PAddr VirtualToPhysicalAddress(const VAddr addr) {
647 auto paddr = TryVirtualToPhysicalAddress(addr); 685 auto paddr = TryVirtualToPhysicalAddress(addr);
648 if (!paddr) { 686 if (!paddr) {
649 LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%016" PRIX64, addr); 687 NGLOG_ERROR(HW_Memory, "Unknown virtual address @ {:#018X}", addr);
650 // To help with debugging, set bit on address so that it's obviously invalid. 688 // To help with debugging, set bit on address so that it's obviously invalid.
651 return addr | 0x80000000; 689 return addr | 0x80000000;
652 } 690 }