From 340167676828bf4595bc267c927f156a11b288aa Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Fri, 2 Apr 2021 17:06:21 -0700
Subject: [PATCH] core: memory: Add a work-around to allocate and access kernel
 memory regions by vaddr.

---
 src/core/core.cpp   |  1 +
 src/core/memory.cpp | 30 +++++++++++++++++++++++++++++-
 src/core/memory.h   | 16 ++++++++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/src/core/core.cpp b/src/core/core.cpp
index d459d6c344..66500a0d4e 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -311,6 +311,7 @@ struct System::Impl {
         gpu_core.reset();
         perf_stats.reset();
         kernel.Shutdown();
+        memory.Reset();
         applet_manager.ClearAll();
 
         LOG_DEBUG(Core, "Shutdown OK");
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index b9dd3e275f..ee4599063d 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -82,6 +82,22 @@ struct Memory::Impl {
         return nullptr;
     }
 
+    u8* GetKernelBuffer(VAddr start_vaddr, size_t size) {
+        // TODO(bunnei): This is just a workaround until we have kernel memory layout mapped &
+        // managed. Until then, we use this to allocate and access kernel memory regions.
+
+        auto search = kernel_memory_regions.find(start_vaddr);
+        if (search != kernel_memory_regions.end()) {
+            return search->second.get();
+        }
+
+        std::unique_ptr<u8[]> new_memory_region{new u8[size]};
+        u8* raw_ptr = new_memory_region.get();
+        kernel_memory_regions[start_vaddr] = std::move(new_memory_region);
+
+        return raw_ptr;
+    }
+
     u8 Read8(const VAddr addr) {
         return Read<u8>(addr);
     }
@@ -711,12 +727,20 @@ struct Memory::Impl {
     }
 
     Common::PageTable* current_page_table = nullptr;
+    std::unordered_map<VAddr, std::unique_ptr<u8[]>> kernel_memory_regions;
     Core::System& system;
 };
 
-Memory::Memory(Core::System& system) : impl{std::make_unique<Impl>(system)} {}
+Memory::Memory(Core::System& system_) : system{system_} {
+    Reset();
+}
+
 Memory::~Memory() = default;
 
+void Memory::Reset() {
+    impl = std::make_unique<Impl>(system);
+}
+
 void Memory::SetCurrentPageTable(Kernel::Process& process, u32 core_id) {
     impl->SetCurrentPageTable(process, core_id);
 }
@@ -741,6 +765,10 @@ u8* Memory::GetPointer(VAddr vaddr) {
     return impl->GetPointer(vaddr);
 }
 
+u8* Memory::GetKernelBuffer(VAddr start_vaddr, size_t size) {
+    return impl->GetKernelBuffer(start_vaddr, size);
+}
+
 const u8* Memory::GetPointer(VAddr vaddr) const {
     return impl->GetPointer(vaddr);
 }
diff --git a/src/core/memory.h b/src/core/memory.h
index 6d34fcfe26..9a706a9ac9 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -58,6 +58,11 @@ public:
     Memory(Memory&&) = default;
     Memory& operator=(Memory&&) = default;
 
+    /**
+     * Resets the state of the Memory system.
+     */
+    void Reset();
+
     /**
      * Changes the currently active page table to that of the given process instance.
      *
@@ -116,6 +121,15 @@ public:
      */
     u8* GetPointer(VAddr vaddr);
 
+    /**
+     * Gets a pointer to the start of a kernel heap allocated memory region. Will allocate one if it
+     * does not already exist.
+     *
+     * @param start_vaddr Start virtual address for the memory region.
+     * @param size Size of the memory region.
+     */
+    u8* GetKernelBuffer(VAddr start_vaddr, size_t size);
+
     template <typename T>
     T* GetPointer(VAddr vaddr) {
         return reinterpret_cast<T*>(GetPointer(vaddr));
@@ -524,6 +538,8 @@ public:
     void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached);
 
 private:
+    Core::System& system;
+
     struct Impl;
     std::unique_ptr<Impl> impl;
 };