From f7c03610e150e49632354e838052d210c8c6075b Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Wed, 8 Apr 2020 22:50:46 -0400
Subject: [PATCH] core: memory: Updates for new VMM.

---
 src/core/memory.cpp | 152 +++++++++++++++-----------------------------
 src/core/memory.h   |  15 +----
 2 files changed, 53 insertions(+), 114 deletions(-)

diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 72d1caf735..fd892b762c 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -14,9 +14,10 @@
 #include "common/swap.h"
 #include "core/arm/arm_interface.h"
 #include "core/core.h"
+#include "core/device_memory.h"
+#include "core/hle/kernel/memory/page_table.h"
 #include "core/hle/kernel/physical_memory.h"
 #include "core/hle/kernel/process.h"
-#include "core/hle/kernel/vm_manager.h"
 #include "core/memory.h"
 #include "video_core/gpu.h"
 
@@ -29,9 +30,9 @@ struct Memory::Impl {
     explicit Impl(Core::System& system_) : system{system_} {}
 
     void SetCurrentPageTable(Kernel::Process& process) {
-        current_page_table = &process.VMManager().page_table;
+        current_page_table = &process.PageTable().PageTableImpl();
 
-        const std::size_t address_space_width = process.VMManager().GetAddressSpaceWidth();
+        const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth();
 
         system.ArmInterface(0).PageTableChanged(*current_page_table, address_space_width);
         system.ArmInterface(1).PageTableChanged(*current_page_table, address_space_width);
@@ -39,12 +40,7 @@ struct Memory::Impl {
         system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width);
     }
 
-    void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size,
-                         Kernel::PhysicalMemory& memory, VAddr offset) {
-        MapMemoryRegion(page_table, base, size, memory.data() + offset);
-    }
-
-    void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
+    void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) {
         ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
         ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
         MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory);
@@ -52,46 +48,27 @@ struct Memory::Impl {
 
     void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size,
                      Common::MemoryHookPointer mmio_handler) {
-        ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
-        ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
-        MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr,
-                 Common::PageType::Special);
-
-        const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
-        const Common::SpecialRegion region{Common::SpecialRegion::Type::IODevice,
-                                           std::move(mmio_handler)};
-        page_table.special_regions.add(
-            std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
+        UNIMPLEMENTED();
     }
 
     void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) {
         ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
         ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
-        MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr,
-                 Common::PageType::Unmapped);
-
-        const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
-        page_table.special_regions.erase(interval);
+        MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, 0, Common::PageType::Unmapped);
     }
 
     void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
                       Common::MemoryHookPointer hook) {
-        const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
-        const Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)};
-        page_table.special_regions.add(
-            std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
+        UNIMPLEMENTED();
     }
 
     void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
                          Common::MemoryHookPointer hook) {
-        const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
-        const Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)};
-        page_table.special_regions.subtract(
-            std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
+        UNIMPLEMENTED();
     }
 
     bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const {
-        const auto& page_table = process.VMManager().page_table;
+        const auto& page_table = process.PageTable().PageTableImpl();
 
         const u8* const page_pointer = page_table.pointers[vaddr >> PAGE_BITS];
         if (page_pointer != nullptr) {
@@ -113,55 +90,28 @@ struct Memory::Impl {
         return IsValidVirtualAddress(*system.CurrentProcess(), vaddr);
     }
 
-    /**
-     * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned)
-     * using a VMA from the current process
-     */
-    u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) {
-        const auto& vm_manager = process.VMManager();
+    u8* GetPointerFromRasterizerCachedMemory(VAddr vaddr) const {
+        const PAddr paddr{current_page_table->backing_addr[vaddr >> PAGE_BITS]};
 
-        const auto it = vm_manager.FindVMA(vaddr);
-        DEBUG_ASSERT(vm_manager.IsValidHandle(it));
-
-        u8* direct_pointer = nullptr;
-        const auto& vma = it->second;
-        switch (vma.type) {
-        case Kernel::VMAType::AllocatedMemoryBlock:
-            direct_pointer = vma.backing_block->data() + vma.offset;
-            break;
-        case Kernel::VMAType::BackingMemory:
-            direct_pointer = vma.backing_memory;
-            break;
-        case Kernel::VMAType::Free:
-            return nullptr;
-        default:
-            UNREACHABLE();
+        if (!paddr) {
+            return {};
         }
 
-        return direct_pointer + (vaddr - vma.base);
+        return system.DeviceMemory().GetPointer(paddr) + vaddr;
     }
 
-    /**
-     * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned)
-     * using a VMA from the current process.
-     */
-    u8* GetPointerFromVMA(VAddr vaddr) {
-        return GetPointerFromVMA(*system.CurrentProcess(), vaddr);
-    }
-
-    u8* GetPointer(const VAddr vaddr) {
-        u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
-        if (page_pointer != nullptr) {
+    u8* GetPointer(const VAddr vaddr) const {
+        u8* const page_pointer{current_page_table->pointers[vaddr >> PAGE_BITS]};
+        if (page_pointer) {
             return page_pointer + vaddr;
         }
 
         if (current_page_table->attributes[vaddr >> PAGE_BITS] ==
             Common::PageType::RasterizerCachedMemory) {
-            return GetPointerFromVMA(vaddr);
+            return GetPointerFromRasterizerCachedMemory(vaddr);
         }
 
-        LOG_ERROR(HW_Memory, "Unknown GetPointer @ 0x{:016X}", vaddr);
-        return nullptr;
+        return {};
     }
 
     u8 Read8(const VAddr addr) {
@@ -213,7 +163,7 @@ struct Memory::Impl {
 
     void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
                    const std::size_t size) {
-        const auto& page_table = process.VMManager().page_table;
+        const auto& page_table = process.PageTable().PageTableImpl();
 
         std::size_t remaining_size = size;
         std::size_t page_index = src_addr >> PAGE_BITS;
@@ -241,7 +191,7 @@ struct Memory::Impl {
                 break;
             }
             case Common::PageType::RasterizerCachedMemory: {
-                const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+                const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
                 system.GPU().FlushRegion(current_vaddr, copy_amount);
                 std::memcpy(dest_buffer, host_ptr, copy_amount);
                 break;
@@ -259,7 +209,7 @@ struct Memory::Impl {
 
     void ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
                          const std::size_t size) {
-        const auto& page_table = process.VMManager().page_table;
+        const auto& page_table = process.PageTable().PageTableImpl();
 
         std::size_t remaining_size = size;
         std::size_t page_index = src_addr >> PAGE_BITS;
@@ -287,7 +237,7 @@ struct Memory::Impl {
                 break;
             }
             case Common::PageType::RasterizerCachedMemory: {
-                const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+                const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
                 std::memcpy(dest_buffer, host_ptr, copy_amount);
                 break;
             }
@@ -312,7 +262,7 @@ struct Memory::Impl {
 
     void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer,
                     const std::size_t size) {
-        const auto& page_table = process.VMManager().page_table;
+        const auto& page_table = process.PageTable().PageTableImpl();
         std::size_t remaining_size = size;
         std::size_t page_index = dest_addr >> PAGE_BITS;
         std::size_t page_offset = dest_addr & PAGE_MASK;
@@ -338,7 +288,7 @@ struct Memory::Impl {
                 break;
             }
             case Common::PageType::RasterizerCachedMemory: {
-                u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+                u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
                 system.GPU().InvalidateRegion(current_vaddr, copy_amount);
                 std::memcpy(host_ptr, src_buffer, copy_amount);
                 break;
@@ -356,7 +306,7 @@ struct Memory::Impl {
 
     void WriteBlockUnsafe(const Kernel::Process& process, const VAddr dest_addr,
                           const void* src_buffer, const std::size_t size) {
-        const auto& page_table = process.VMManager().page_table;
+        const auto& page_table = process.PageTable().PageTableImpl();
         std::size_t remaining_size = size;
         std::size_t page_index = dest_addr >> PAGE_BITS;
         std::size_t page_offset = dest_addr & PAGE_MASK;
@@ -382,7 +332,7 @@ struct Memory::Impl {
                 break;
             }
             case Common::PageType::RasterizerCachedMemory: {
-                u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+                u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
                 std::memcpy(host_ptr, src_buffer, copy_amount);
                 break;
             }
@@ -406,7 +356,7 @@ struct Memory::Impl {
     }
 
     void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) {
-        const auto& page_table = process.VMManager().page_table;
+        const auto& page_table = process.PageTable().PageTableImpl();
         std::size_t remaining_size = size;
         std::size_t page_index = dest_addr >> PAGE_BITS;
         std::size_t page_offset = dest_addr & PAGE_MASK;
@@ -432,7 +382,7 @@ struct Memory::Impl {
                 break;
             }
             case Common::PageType::RasterizerCachedMemory: {
-                u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+                u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
                 system.GPU().InvalidateRegion(current_vaddr, copy_amount);
                 std::memset(host_ptr, 0, copy_amount);
                 break;
@@ -453,7 +403,7 @@ struct Memory::Impl {
 
     void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
                    const std::size_t size) {
-        const auto& page_table = process.VMManager().page_table;
+        const auto& page_table = process.PageTable().PageTableImpl();
         std::size_t remaining_size = size;
         std::size_t page_index = src_addr >> PAGE_BITS;
         std::size_t page_offset = src_addr & PAGE_MASK;
@@ -479,7 +429,7 @@ struct Memory::Impl {
                 break;
             }
             case Common::PageType::RasterizerCachedMemory: {
-                const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
+                const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
                 system.GPU().FlushRegion(current_vaddr, copy_amount);
                 WriteBlock(process, dest_addr, host_ptr, copy_amount);
                 break;
@@ -512,7 +462,7 @@ struct Memory::Impl {
 
         u64 num_pages = ((vaddr + size - 1) >> PAGE_BITS) - (vaddr >> PAGE_BITS) + 1;
         for (unsigned i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) {
-            Common::PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS];
+            Common::PageType& page_type{current_page_table->attributes[vaddr >> PAGE_BITS]};
 
             if (cached) {
                 // Switch page type to cached if now cached
@@ -544,7 +494,7 @@ struct Memory::Impl {
                     // that this area is already unmarked as cached.
                     break;
                 case Common::PageType::RasterizerCachedMemory: {
-                    u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK);
+                    u8* pointer{GetPointerFromRasterizerCachedMemory(vaddr & ~PAGE_MASK)};
                     if (pointer == nullptr) {
                         // It's possible that this function has been called while updating the
                         // pagetable after unmapping a VMA. In that case the underlying VMA will no
@@ -573,9 +523,9 @@ struct Memory::Impl {
      * @param memory     The memory to map.
      * @param type       The page type to map the memory as.
      */
-    void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory,
+    void MapPages(Common::PageTable& page_table, VAddr base, u64 size, PAddr target,
                   Common::PageType type) {
-        LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE,
+        LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", target, base * PAGE_SIZE,
                   (base + size) * PAGE_SIZE);
 
         // During boot, current_page_table might not be set yet, in which case we need not flush
@@ -593,19 +543,26 @@ struct Memory::Impl {
         ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}",
                    base + page_table.pointers.size());
 
-        std::fill(page_table.attributes.begin() + base, page_table.attributes.begin() + end, type);
+        if (!target) {
+            while (base != end) {
+                page_table.pointers[base] = nullptr;
+                page_table.attributes[base] = type;
+                page_table.backing_addr[base] = 0;
 
-        if (memory == nullptr) {
-            std::fill(page_table.pointers.begin() + base, page_table.pointers.begin() + end,
-                      memory);
+                base += 1;
+            }
         } else {
             while (base != end) {
-                page_table.pointers[base] = memory - (base << PAGE_BITS);
+                page_table.pointers[base] =
+                    system.DeviceMemory().GetPointer(target) - (base << PAGE_BITS);
+                page_table.attributes[base] = type;
+                page_table.backing_addr[base] = target - (base << PAGE_BITS);
+
                 ASSERT_MSG(page_table.pointers[base],
                            "memory mapping base yield a nullptr within the table");
 
                 base += 1;
-                memory += PAGE_SIZE;
+                target += PAGE_SIZE;
             }
         }
     }
@@ -640,7 +597,7 @@ struct Memory::Impl {
             ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
             break;
         case Common::PageType::RasterizerCachedMemory: {
-            const u8* const host_ptr = GetPointerFromVMA(vaddr);
+            const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
             system.GPU().FlushRegion(vaddr, sizeof(T));
             T value;
             std::memcpy(&value, host_ptr, sizeof(T));
@@ -682,7 +639,7 @@ struct Memory::Impl {
             ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
             break;
         case Common::PageType::RasterizerCachedMemory: {
-            u8* const host_ptr{GetPointerFromVMA(vaddr)};
+            u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
             system.GPU().InvalidateRegion(vaddr, sizeof(T));
             std::memcpy(host_ptr, &data, sizeof(T));
             break;
@@ -703,12 +660,7 @@ void Memory::SetCurrentPageTable(Kernel::Process& process) {
     impl->SetCurrentPageTable(process);
 }
 
-void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size,
-                             Kernel::PhysicalMemory& memory, VAddr offset) {
-    impl->MapMemoryRegion(page_table, base, size, memory, offset);
-}
-
-void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
+void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) {
     impl->MapMemoryRegion(page_table, base, size, target);
 }
 
diff --git a/src/core/memory.h b/src/core/memory.h
index f6d9e8e8cd..9292f3b0ae 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -66,19 +66,6 @@ public:
      */
     void SetCurrentPageTable(Kernel::Process& process);
 
-    /**
-     * Maps an physical buffer onto a region of the emulated process address space.
-     *
-     * @param page_table The page table of the emulated process.
-     * @param base       The address to start mapping at. Must be page-aligned.
-     * @param size       The amount of bytes to map. Must be page-aligned.
-     * @param memory     Physical buffer with the memory backing the mapping. Must be of length
-     *                   at least `size + offset`.
-     * @param offset     The offset within the physical memory. Must be page-aligned.
-     */
-    void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size,
-                         Kernel::PhysicalMemory& memory, VAddr offset);
-
     /**
      * Maps an allocated buffer onto a region of the emulated process address space.
      *
@@ -88,7 +75,7 @@ public:
      * @param target     Buffer with the memory backing the mapping. Must be of length at least
      *                   `size`.
      */
-    void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target);
+    void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target);
 
     /**
      * Maps a region of the emulated process address space as a IO region.