summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Lioncash2019-11-26 13:09:12 -0500
committerGravatar Lioncash2019-11-26 21:53:34 -0500
commit323680e5ad3ca0e27f2dd1de26816741b3243bed (patch)
treeac7a9e683831493f0f14c8b9566c0d570807ad62 /src/core
parentcore/memory: Introduce skeleton of Memory class (diff)
downloadyuzu-323680e5ad3ca0e27f2dd1de26816741b3243bed.tar.gz
yuzu-323680e5ad3ca0e27f2dd1de26816741b3243bed.tar.xz
yuzu-323680e5ad3ca0e27f2dd1de26816741b3243bed.zip
core/memory: Migrate over memory mapping functions to the new Memory class
Migrates all of the direct mapping facilities over to the new memory class. In the process, this also obsoletes the need for memory_setup.h, so we can remove it entirely from the project.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/kernel/vm_manager.cpp13
-rw-r--r--src/core/memory.cpp177
-rw-r--r--src/core/memory.h59
-rw-r--r--src/core/memory_setup.h43
5 files changed, 172 insertions, 121 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f2e774a6b..2dfdcb0d7 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -509,7 +509,6 @@ add_library(core STATIC
509 memory/dmnt_cheat_vm.h 509 memory/dmnt_cheat_vm.h
510 memory.cpp 510 memory.cpp
511 memory.h 511 memory.h
512 memory_setup.h
513 perf_stats.cpp 512 perf_stats.cpp
514 perf_stats.h 513 perf_stats.h
515 reporter.cpp 514 reporter.cpp
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index e6eee09d7..a9a20ef76 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -16,7 +16,6 @@
16#include "core/hle/kernel/resource_limit.h" 16#include "core/hle/kernel/resource_limit.h"
17#include "core/hle/kernel/vm_manager.h" 17#include "core/hle/kernel/vm_manager.h"
18#include "core/memory.h" 18#include "core/memory.h"
19#include "core/memory_setup.h"
20 19
21namespace Kernel { 20namespace Kernel {
22namespace { 21namespace {
@@ -786,19 +785,21 @@ void VMManager::MergeAdjacentVMA(VirtualMemoryArea& left, const VirtualMemoryAre
786} 785}
787 786
788void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) { 787void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
788 auto& memory = system.Memory();
789
789 switch (vma.type) { 790 switch (vma.type) {
790 case VMAType::Free: 791 case VMAType::Free:
791 Memory::UnmapRegion(page_table, vma.base, vma.size); 792 memory.UnmapRegion(page_table, vma.base, vma.size);
792 break; 793 break;
793 case VMAType::AllocatedMemoryBlock: 794 case VMAType::AllocatedMemoryBlock:
794 Memory::MapMemoryRegion(page_table, vma.base, vma.size, 795 memory.MapMemoryRegion(page_table, vma.base, vma.size,
795 vma.backing_block->data() + vma.offset); 796 vma.backing_block->data() + vma.offset);
796 break; 797 break;
797 case VMAType::BackingMemory: 798 case VMAType::BackingMemory:
798 Memory::MapMemoryRegion(page_table, vma.base, vma.size, vma.backing_memory); 799 memory.MapMemoryRegion(page_table, vma.base, vma.size, vma.backing_memory);
799 break; 800 break;
800 case VMAType::MMIO: 801 case VMAType::MMIO:
801 Memory::MapIoRegion(page_table, vma.base, vma.size, vma.mmio_handler); 802 memory.MapIoRegion(page_table, vma.base, vma.size, vma.mmio_handler);
802 break; 803 break;
803 } 804 }
804} 805}
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 2098f13f7..28b65ca5e 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -17,7 +17,6 @@
17#include "core/hle/kernel/process.h" 17#include "core/hle/kernel/process.h"
18#include "core/hle/kernel/vm_manager.h" 18#include "core/hle/kernel/vm_manager.h"
19#include "core/memory.h" 19#include "core/memory.h"
20#include "core/memory_setup.h"
21#include "video_core/gpu.h" 20#include "video_core/gpu.h"
22 21
23namespace Memory { 22namespace Memory {
@@ -30,99 +29,135 @@ static Common::PageTable* current_page_table = nullptr;
30struct Memory::Impl { 29struct Memory::Impl {
31 explicit Impl(Core::System& system_) : system{system_} {} 30 explicit Impl(Core::System& system_) : system{system_} {}
32 31
33 Core::System& system; 32 void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
34}; 33 ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
34 ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
35 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory);
36 }
35 37
36Memory::Memory(Core::System& system) : impl{std::make_unique<Impl>(system)} {} 38 void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size,
37Memory::~Memory() = default; 39 Common::MemoryHookPointer mmio_handler) {
40 ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
41 ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
42 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr,
43 Common::PageType::Special);
44
45 const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
46 const Common::SpecialRegion region{Common::SpecialRegion::Type::IODevice,
47 std::move(mmio_handler)};
48 page_table.special_regions.add(
49 std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
50 }
38 51
39void SetCurrentPageTable(Kernel::Process& process) { 52 void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) {
40 current_page_table = &process.VMManager().page_table; 53 ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
54 ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
55 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr,
56 Common::PageType::Unmapped);
41 57
42 const std::size_t address_space_width = process.VMManager().GetAddressSpaceWidth(); 58 const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
59 page_table.special_regions.erase(interval);
60 }
43 61
44 auto& system = Core::System::GetInstance(); 62 void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
45 system.ArmInterface(0).PageTableChanged(*current_page_table, address_space_width); 63 Common::MemoryHookPointer hook) {
46 system.ArmInterface(1).PageTableChanged(*current_page_table, address_space_width); 64 const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
47 system.ArmInterface(2).PageTableChanged(*current_page_table, address_space_width); 65 const Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)};
48 system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width); 66 page_table.special_regions.add(
49} 67 std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
68 }
69
70 void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
71 Common::MemoryHookPointer hook) {
72 const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1);
73 const Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)};
74 page_table.special_regions.subtract(
75 std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
76 }
50 77
51static void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory, 78 /**
52 Common::PageType type) { 79 * Maps a region of pages as a specific type.
53 LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE, 80 *
54 (base + size) * PAGE_SIZE); 81 * @param page_table The page table to use to perform the mapping.
55 82 * @param base The base address to begin mapping at.
56 // During boot, current_page_table might not be set yet, in which case we need not flush 83 * @param size The total size of the range in bytes.
57 if (Core::System::GetInstance().IsPoweredOn()) { 84 * @param memory The memory to map.
58 auto& gpu = Core::System::GetInstance().GPU(); 85 * @param type The page type to map the memory as.
59 for (u64 i = 0; i < size; i++) { 86 */
60 const auto page = base + i; 87 void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory,
61 if (page_table.attributes[page] == Common::PageType::RasterizerCachedMemory) { 88 Common::PageType type) {
62 gpu.FlushAndInvalidateRegion(page << PAGE_BITS, PAGE_SIZE); 89 LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE,
90 (base + size) * PAGE_SIZE);
91
92 // During boot, current_page_table might not be set yet, in which case we need not flush
93 if (system.IsPoweredOn()) {
94 auto& gpu = system.GPU();
95 for (u64 i = 0; i < size; i++) {
96 const auto page = base + i;
97 if (page_table.attributes[page] == Common::PageType::RasterizerCachedMemory) {
98 gpu.FlushAndInvalidateRegion(page << PAGE_BITS, PAGE_SIZE);
99 }
63 } 100 }
64 } 101 }
65 }
66 102
67 VAddr end = base + size; 103 const VAddr end = base + size;
68 ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}", 104 ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}",
69 base + page_table.pointers.size()); 105 base + page_table.pointers.size());
70 106
71 std::fill(page_table.attributes.begin() + base, page_table.attributes.begin() + end, type); 107 std::fill(page_table.attributes.begin() + base, page_table.attributes.begin() + end, type);
72 108
73 if (memory == nullptr) { 109 if (memory == nullptr) {
74 std::fill(page_table.pointers.begin() + base, page_table.pointers.begin() + end, memory); 110 std::fill(page_table.pointers.begin() + base, page_table.pointers.begin() + end,
75 } else { 111 memory);
76 while (base != end) { 112 } else {
77 page_table.pointers[base] = memory; 113 while (base != end) {
114 page_table.pointers[base] = memory;
78 115
79 base += 1; 116 base += 1;
80 memory += PAGE_SIZE; 117 memory += PAGE_SIZE;
118 }
81 } 119 }
82 } 120 }
83}
84 121
85void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) { 122 Core::System& system;
86 ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); 123};
87 ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
88 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory);
89}
90 124
91void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size, 125Memory::Memory(Core::System& system) : impl{std::make_unique<Impl>(system)} {}
92 Common::MemoryHookPointer mmio_handler) { 126Memory::~Memory() = default;
93 ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
94 ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
95 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr, Common::PageType::Special);
96 127
97 auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1); 128void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
98 Common::SpecialRegion region{Common::SpecialRegion::Type::IODevice, std::move(mmio_handler)}; 129 impl->MapMemoryRegion(page_table, base, size, target);
99 page_table.special_regions.add(
100 std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
101} 130}
102 131
103void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { 132void Memory::MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size,
104 ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); 133 Common::MemoryHookPointer mmio_handler) {
105 ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); 134 impl->MapIoRegion(page_table, base, size, std::move(mmio_handler));
106 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr, Common::PageType::Unmapped); 135}
136
137void Memory::UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) {
138 impl->UnmapRegion(page_table, base, size);
139}
107 140
108 auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1); 141void Memory::AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
109 page_table.special_regions.erase(interval); 142 Common::MemoryHookPointer hook) {
143 impl->AddDebugHook(page_table, base, size, std::move(hook));
110} 144}
111 145
112void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size, 146void Memory::RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
113 Common::MemoryHookPointer hook) { 147 Common::MemoryHookPointer hook) {
114 auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1); 148 impl->RemoveDebugHook(page_table, base, size, std::move(hook));
115 Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)};
116 page_table.special_regions.add(
117 std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
118} 149}
119 150
120void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size, 151void SetCurrentPageTable(Kernel::Process& process) {
121 Common::MemoryHookPointer hook) { 152 current_page_table = &process.VMManager().page_table;
122 auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1); 153
123 Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)}; 154 const std::size_t address_space_width = process.VMManager().GetAddressSpaceWidth();
124 page_table.special_regions.subtract( 155
125 std::make_pair(interval, std::set<Common::SpecialRegion>{region})); 156 auto& system = Core::System::GetInstance();
157 system.ArmInterface(0).PageTableChanged(*current_page_table, address_space_width);
158 system.ArmInterface(1).PageTableChanged(*current_page_table, address_space_width);
159 system.ArmInterface(2).PageTableChanged(*current_page_table, address_space_width);
160 system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width);
126} 161}
127 162
128/** 163/**
diff --git a/src/core/memory.h b/src/core/memory.h
index c690df3c3..87ed3b696 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -5,8 +5,14 @@
5#pragma once 5#pragma once
6 6
7#include <cstddef> 7#include <cstddef>
8#include <memory>
8#include <string> 9#include <string>
9#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/memory_hook.h"
12
13namespace Common {
14struct PageTable;
15}
10 16
11namespace Core { 17namespace Core {
12class System; 18class System;
@@ -52,6 +58,59 @@ public:
52 Memory(Memory&&) = default; 58 Memory(Memory&&) = default;
53 Memory& operator=(Memory&&) = default; 59 Memory& operator=(Memory&&) = default;
54 60
61 /**
62 * Maps an allocated buffer onto a region of the emulated process address space.
63 *
64 * @param page_table The page table of the emulated process.
65 * @param base The address to start mapping at. Must be page-aligned.
66 * @param size The amount of bytes to map. Must be page-aligned.
67 * @param target Buffer with the memory backing the mapping. Must be of length at least
68 * `size`.
69 */
70 void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target);
71
72 /**
73 * Maps a region of the emulated process address space as a IO region.
74 *
75 * @param page_table The page table of the emulated process.
76 * @param base The address to start mapping at. Must be page-aligned.
77 * @param size The amount of bytes to map. Must be page-aligned.
78 * @param mmio_handler The handler that backs the mapping.
79 */
80 void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size,
81 Common::MemoryHookPointer mmio_handler);
82
83 /**
84 * Unmaps a region of the emulated process address space.
85 *
86 * @param page_table The page table of the emulated process.
87 * @param base The address to begin unmapping at.
88 * @param size The amount of bytes to unmap.
89 */
90 void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size);
91
92 /**
93 * Adds a memory hook to intercept reads and writes to given region of memory.
94 *
95 * @param page_table The page table of the emulated process
96 * @param base The starting address to apply the hook to.
97 * @param size The size of the memory region to apply the hook to, in bytes.
98 * @param hook The hook to apply to the region of memory.
99 */
100 void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
101 Common::MemoryHookPointer hook);
102
103 /**
104 * Removes a memory hook from a given range of memory.
105 *
106 * @param page_table The page table of the emulated process.
107 * @param base The starting address to remove the hook from.
108 * @param size The size of the memory region to remove the hook from, in bytes.
109 * @param hook The hook to remove from the specified region of memory.
110 */
111 void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
112 Common::MemoryHookPointer hook);
113
55private: 114private:
56 struct Impl; 115 struct Impl;
57 std::unique_ptr<Impl> impl; 116 std::unique_ptr<Impl> impl;
diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h
deleted file mode 100644
index 5225ee8e2..000000000
--- a/src/core/memory_setup.h
+++ /dev/null
@@ -1,43 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8#include "common/memory_hook.h"
9
10namespace Common {
11struct PageTable;
12}
13
14namespace Memory {
15
16/**
17 * Maps an allocated buffer onto a region of the emulated process address space.
18 *
19 * @param page_table The page table of the emulated process.
20 * @param base The address to start mapping at. Must be page-aligned.
21 * @param size The amount of bytes to map. Must be page-aligned.
22 * @param target Buffer with the memory backing the mapping. Must be of length at least `size`.
23 */
24void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target);
25
26/**
27 * Maps a region of the emulated process address space as a IO region.
28 * @param page_table The page table of the emulated process.
29 * @param base The address to start mapping at. Must be page-aligned.
30 * @param size The amount of bytes to map. Must be page-aligned.
31 * @param mmio_handler The handler that backs the mapping.
32 */
33void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size,
34 Common::MemoryHookPointer mmio_handler);
35
36void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size);
37
38void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
39 Common::MemoryHookPointer hook);
40void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
41 Common::MemoryHookPointer hook);
42
43} // namespace Memory