summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/memory_hook.cpp11
-rw-r--r--src/common/memory_hook.h47
-rw-r--r--src/common/page_table.h18
-rw-r--r--src/core/memory.cpp30
-rw-r--r--src/core/memory.h34
-rw-r--r--src/tests/CMakeLists.txt2
-rw-r--r--src/tests/core/arm/arm_test_common.cpp145
-rw-r--r--src/tests/core/arm/arm_test_common.h93
9 files changed, 0 insertions, 382 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 5c8003eb1..2c2bd2ee8 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -135,8 +135,6 @@ add_library(common STATIC
135 math_util.h 135 math_util.h
136 memory_detect.cpp 136 memory_detect.cpp
137 memory_detect.h 137 memory_detect.h
138 memory_hook.cpp
139 memory_hook.h
140 microprofile.cpp 138 microprofile.cpp
141 microprofile.h 139 microprofile.h
142 microprofileui.h 140 microprofileui.h
diff --git a/src/common/memory_hook.cpp b/src/common/memory_hook.cpp
deleted file mode 100644
index 3986986d6..000000000
--- a/src/common/memory_hook.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
1// Copyright 2018 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/memory_hook.h"
6
7namespace Common {
8
9MemoryHook::~MemoryHook() = default;
10
11} // namespace Common
diff --git a/src/common/memory_hook.h b/src/common/memory_hook.h
deleted file mode 100644
index adaa4c2c5..000000000
--- a/src/common/memory_hook.h
+++ /dev/null
@@ -1,47 +0,0 @@
1// Copyright 2016 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 <memory>
8#include <optional>
9
10#include "common/common_types.h"
11
12namespace Common {
13
14/**
15 * Memory hooks have two purposes:
16 * 1. To allow reads and writes to a region of memory to be intercepted. This is used to implement
17 * texture forwarding and memory breakpoints for debugging.
18 * 2. To allow for the implementation of MMIO devices.
19 *
20 * A hook may be mapped to multiple regions of memory.
21 *
22 * If a std::nullopt or false is returned from a function, the read/write request is passed through
23 * to the underlying memory region.
24 */
25class MemoryHook {
26public:
27 virtual ~MemoryHook();
28
29 virtual std::optional<bool> IsValidAddress(VAddr addr) = 0;
30
31 virtual std::optional<u8> Read8(VAddr addr) = 0;
32 virtual std::optional<u16> Read16(VAddr addr) = 0;
33 virtual std::optional<u32> Read32(VAddr addr) = 0;
34 virtual std::optional<u64> Read64(VAddr addr) = 0;
35
36 virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) = 0;
37
38 virtual bool Write8(VAddr addr, u8 data) = 0;
39 virtual bool Write16(VAddr addr, u16 data) = 0;
40 virtual bool Write32(VAddr addr, u32 data) = 0;
41 virtual bool Write64(VAddr addr, u64 data) = 0;
42
43 virtual bool WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size) = 0;
44};
45
46using MemoryHookPointer = std::shared_ptr<MemoryHook>;
47} // namespace Common
diff --git a/src/common/page_table.h b/src/common/page_table.h
index 8d4ee9249..0c14e6433 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -8,7 +8,6 @@
8#include <tuple> 8#include <tuple>
9 9
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/memory_hook.h"
12#include "common/virtual_buffer.h" 11#include "common/virtual_buffer.h"
13 12
14namespace Common { 13namespace Common {
@@ -23,23 +22,6 @@ enum class PageType : u8 {
23 RasterizerCachedMemory, 22 RasterizerCachedMemory,
24}; 23};
25 24
26struct SpecialRegion {
27 enum class Type {
28 DebugHook,
29 IODevice,
30 } type;
31
32 MemoryHookPointer handler;
33
34 [[nodiscard]] bool operator<(const SpecialRegion& other) const {
35 return std::tie(type, handler) < std::tie(other.type, other.handler);
36 }
37
38 [[nodiscard]] bool operator==(const SpecialRegion& other) const {
39 return std::tie(type, handler) == std::tie(other.type, other.handler);
40 }
41};
42
43/** 25/**
44 * A (reasonably) fast way of allowing switchable and remappable process address spaces. It loosely 26 * A (reasonably) fast way of allowing switchable and remappable process address spaces. It loosely
45 * mimics the way a real CPU page table works. 27 * mimics the way a real CPU page table works.
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index f209c4949..11609682a 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -44,27 +44,12 @@ struct Memory::Impl {
44 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory); 44 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory);
45 } 45 }
46 46
47 void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size,
48 Common::MemoryHookPointer mmio_handler) {
49 UNIMPLEMENTED();
50 }
51
52 void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { 47 void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) {
53 ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); 48 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); 49 ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
55 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, 0, Common::PageType::Unmapped); 50 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, 0, Common::PageType::Unmapped);
56 } 51 }
57 52
58 void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
59 Common::MemoryHookPointer hook) {
60 UNIMPLEMENTED();
61 }
62
63 void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
64 Common::MemoryHookPointer hook) {
65 UNIMPLEMENTED();
66 }
67
68 bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const { 53 bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const {
69 const auto& page_table = process.PageTable().PageTableImpl(); 54 const auto& page_table = process.PageTable().PageTableImpl();
70 const auto [pointer, type] = page_table.pointers[vaddr >> PAGE_BITS].PointerType(); 55 const auto [pointer, type] = page_table.pointers[vaddr >> PAGE_BITS].PointerType();
@@ -740,25 +725,10 @@ void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size
740 impl->MapMemoryRegion(page_table, base, size, target); 725 impl->MapMemoryRegion(page_table, base, size, target);
741} 726}
742 727
743void Memory::MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size,
744 Common::MemoryHookPointer mmio_handler) {
745 impl->MapIoRegion(page_table, base, size, std::move(mmio_handler));
746}
747
748void Memory::UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { 728void Memory::UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) {
749 impl->UnmapRegion(page_table, base, size); 729 impl->UnmapRegion(page_table, base, size);
750} 730}
751 731
752void Memory::AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
753 Common::MemoryHookPointer hook) {
754 impl->AddDebugHook(page_table, base, size, std::move(hook));
755}
756
757void Memory::RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
758 Common::MemoryHookPointer hook) {
759 impl->RemoveDebugHook(page_table, base, size, std::move(hook));
760}
761
762bool Memory::IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const { 732bool Memory::IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const {
763 return impl->IsValidVirtualAddress(process, vaddr); 733 return impl->IsValidVirtualAddress(process, vaddr);
764} 734}
diff --git a/src/core/memory.h b/src/core/memory.h
index 4a1cc63f4..705ebb23d 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -8,7 +8,6 @@
8#include <memory> 8#include <memory>
9#include <string> 9#include <string>
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/memory_hook.h"
12 11
13namespace Common { 12namespace Common {
14struct PageTable; 13struct PageTable;
@@ -78,17 +77,6 @@ public:
78 void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target); 77 void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target);
79 78
80 /** 79 /**
81 * Maps a region of the emulated process address space as a IO region.
82 *
83 * @param page_table The page table of the emulated process.
84 * @param base The address to start mapping at. Must be page-aligned.
85 * @param size The amount of bytes to map. Must be page-aligned.
86 * @param mmio_handler The handler that backs the mapping.
87 */
88 void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size,
89 Common::MemoryHookPointer mmio_handler);
90
91 /**
92 * Unmaps a region of the emulated process address space. 80 * Unmaps a region of the emulated process address space.
93 * 81 *
94 * @param page_table The page table of the emulated process. 82 * @param page_table The page table of the emulated process.
@@ -98,28 +86,6 @@ public:
98 void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size); 86 void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size);
99 87
100 /** 88 /**
101 * Adds a memory hook to intercept reads and writes to given region of memory.
102 *
103 * @param page_table The page table of the emulated process
104 * @param base The starting address to apply the hook to.
105 * @param size The size of the memory region to apply the hook to, in bytes.
106 * @param hook The hook to apply to the region of memory.
107 */
108 void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
109 Common::MemoryHookPointer hook);
110
111 /**
112 * Removes a memory hook from a given range of memory.
113 *
114 * @param page_table The page table of the emulated process.
115 * @param base The starting address to remove the hook from.
116 * @param size The size of the memory region to remove the hook from, in bytes.
117 * @param hook The hook to remove from the specified region of memory.
118 */
119 void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
120 Common::MemoryHookPointer hook);
121
122 /**
123 * Checks whether or not the supplied address is a valid virtual 89 * Checks whether or not the supplied address is a valid virtual
124 * address for the given process. 90 * address for the given process.
125 * 91 *
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index d80b0b688..8a606b448 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -4,8 +4,6 @@ add_executable(tests
4 common/fibers.cpp 4 common/fibers.cpp
5 common/param_package.cpp 5 common/param_package.cpp
6 common/ring_buffer.cpp 6 common/ring_buffer.cpp
7 core/arm/arm_test_common.cpp
8 core/arm/arm_test_common.h
9 core/core_timing.cpp 7 core/core_timing.cpp
10 tests.cpp 8 tests.cpp
11) 9)
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp
deleted file mode 100644
index e54674d11..000000000
--- a/src/tests/core/arm/arm_test_common.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6
7#include "common/page_table.h"
8#include "core/core.h"
9#include "core/hle/kernel/memory/page_table.h"
10#include "core/hle/kernel/process.h"
11#include "core/memory.h"
12#include "tests/core/arm/arm_test_common.h"
13
14namespace ArmTests {
15
16TestEnvironment::TestEnvironment(bool mutable_memory_)
17 : mutable_memory(mutable_memory_),
18 test_memory(std::make_shared<TestMemory>(this)), kernel{Core::System::GetInstance()} {
19 auto& system = Core::System::GetInstance();
20
21 auto process = Kernel::Process::Create(system, "", Kernel::Process::ProcessType::Userland);
22 page_table = &process->PageTable().PageTableImpl();
23
24 system.Memory().MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory);
25 system.Memory().MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory);
26
27 kernel.MakeCurrentProcess(process.get());
28}
29
30TestEnvironment::~TestEnvironment() {
31 auto& system = Core::System::GetInstance();
32 system.Memory().UnmapRegion(*page_table, 0x80000000, 0x80000000);
33 system.Memory().UnmapRegion(*page_table, 0x00000000, 0x80000000);
34}
35
36void TestEnvironment::SetMemory64(VAddr vaddr, u64 value) {
37 SetMemory32(vaddr + 0, static_cast<u32>(value));
38 SetMemory32(vaddr + 4, static_cast<u32>(value >> 32));
39}
40
41void TestEnvironment::SetMemory32(VAddr vaddr, u32 value) {
42 SetMemory16(vaddr + 0, static_cast<u16>(value));
43 SetMemory16(vaddr + 2, static_cast<u16>(value >> 16));
44}
45
46void TestEnvironment::SetMemory16(VAddr vaddr, u16 value) {
47 SetMemory8(vaddr + 0, static_cast<u8>(value));
48 SetMemory8(vaddr + 1, static_cast<u8>(value >> 8));
49}
50
51void TestEnvironment::SetMemory8(VAddr vaddr, u8 value) {
52 test_memory->data[vaddr] = value;
53}
54
55std::vector<WriteRecord> TestEnvironment::GetWriteRecords() const {
56 return write_records;
57}
58
59void TestEnvironment::ClearWriteRecords() {
60 write_records.clear();
61}
62
63TestEnvironment::TestMemory::~TestMemory() {}
64
65std::optional<bool> TestEnvironment::TestMemory::IsValidAddress(VAddr addr) {
66 return true;
67}
68
69std::optional<u8> TestEnvironment::TestMemory::Read8(VAddr addr) {
70 const auto iter = data.find(addr);
71
72 if (iter == data.end()) {
73 // Some arbitrary data
74 return static_cast<u8>(addr);
75 }
76
77 return iter->second;
78}
79
80std::optional<u16> TestEnvironment::TestMemory::Read16(VAddr addr) {
81 return *Read8(addr) | static_cast<u16>(*Read8(addr + 1)) << 8;
82}
83
84std::optional<u32> TestEnvironment::TestMemory::Read32(VAddr addr) {
85 return *Read16(addr) | static_cast<u32>(*Read16(addr + 2)) << 16;
86}
87
88std::optional<u64> TestEnvironment::TestMemory::Read64(VAddr addr) {
89 return *Read32(addr) | static_cast<u64>(*Read32(addr + 4)) << 32;
90}
91
92bool TestEnvironment::TestMemory::ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) {
93 VAddr addr = src_addr;
94 u8* data = static_cast<u8*>(dest_buffer);
95
96 for (std::size_t i = 0; i < size; i++, addr++, data++) {
97 *data = *Read8(addr);
98 }
99
100 return true;
101}
102
103bool TestEnvironment::TestMemory::Write8(VAddr addr, u8 data) {
104 env->write_records.emplace_back(8, addr, data);
105 if (env->mutable_memory)
106 env->SetMemory8(addr, data);
107 return true;
108}
109
110bool TestEnvironment::TestMemory::Write16(VAddr addr, u16 data) {
111 env->write_records.emplace_back(16, addr, data);
112 if (env->mutable_memory)
113 env->SetMemory16(addr, data);
114 return true;
115}
116
117bool TestEnvironment::TestMemory::Write32(VAddr addr, u32 data) {
118 env->write_records.emplace_back(32, addr, data);
119 if (env->mutable_memory)
120 env->SetMemory32(addr, data);
121 return true;
122}
123
124bool TestEnvironment::TestMemory::Write64(VAddr addr, u64 data) {
125 env->write_records.emplace_back(64, addr, data);
126 if (env->mutable_memory)
127 env->SetMemory64(addr, data);
128 return true;
129}
130
131bool TestEnvironment::TestMemory::WriteBlock(VAddr dest_addr, const void* src_buffer,
132 std::size_t size) {
133 VAddr addr = dest_addr;
134 const u8* data = static_cast<const u8*>(src_buffer);
135
136 for (std::size_t i = 0; i < size; i++, addr++, data++) {
137 env->write_records.emplace_back(8, addr, *data);
138 if (env->mutable_memory)
139 env->SetMemory8(addr, *data);
140 }
141
142 return true;
143}
144
145} // namespace ArmTests
diff --git a/src/tests/core/arm/arm_test_common.h b/src/tests/core/arm/arm_test_common.h
deleted file mode 100644
index d145dbfcc..000000000
--- a/src/tests/core/arm/arm_test_common.h
+++ /dev/null
@@ -1,93 +0,0 @@
1// Copyright 2016 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 <tuple>
8#include <unordered_map>
9#include <vector>
10
11#include "common/common_types.h"
12#include "common/memory_hook.h"
13#include "core/hle/kernel/kernel.h"
14
15namespace Common {
16struct PageTable;
17}
18
19namespace ArmTests {
20
21struct WriteRecord {
22 WriteRecord(std::size_t size, VAddr addr, u64 data) : size(size), addr(addr), data(data) {}
23 std::size_t size;
24 VAddr addr;
25 u64 data;
26 bool operator==(const WriteRecord& o) const {
27 return std::tie(size, addr, data) == std::tie(o.size, o.addr, o.data);
28 }
29};
30
31class TestEnvironment final {
32public:
33 /*
34 * Inititalise test environment
35 * @param mutable_memory If false, writes to memory can never be read back.
36 * (Memory is immutable.)
37 */
38 explicit TestEnvironment(bool mutable_memory = false);
39
40 /// Shutdown test environment
41 ~TestEnvironment();
42
43 /// Sets value at memory location vaddr.
44 void SetMemory8(VAddr vaddr, u8 value);
45 void SetMemory16(VAddr vaddr, u16 value);
46 void SetMemory32(VAddr vaddr, u32 value);
47 void SetMemory64(VAddr vaddr, u64 value);
48
49 /**
50 * Whenever Memory::Write{8,16,32,64} is called within the test environment,
51 * a new write-record is made.
52 * @returns A vector of write records made since they were last cleared.
53 */
54 std::vector<WriteRecord> GetWriteRecords() const;
55
56 /// Empties the internal write-record store.
57 void ClearWriteRecords();
58
59private:
60 friend struct TestMemory;
61 struct TestMemory final : Common::MemoryHook {
62 explicit TestMemory(TestEnvironment* env_) : env(env_) {}
63 TestEnvironment* env;
64
65 ~TestMemory() override;
66
67 std::optional<bool> IsValidAddress(VAddr addr) override;
68
69 std::optional<u8> Read8(VAddr addr) override;
70 std::optional<u16> Read16(VAddr addr) override;
71 std::optional<u32> Read32(VAddr addr) override;
72 std::optional<u64> Read64(VAddr addr) override;
73
74 bool ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) override;
75
76 bool Write8(VAddr addr, u8 data) override;
77 bool Write16(VAddr addr, u16 data) override;
78 bool Write32(VAddr addr, u32 data) override;
79 bool Write64(VAddr addr, u64 data) override;
80
81 bool WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size) override;
82
83 std::unordered_map<VAddr, u8> data;
84 };
85
86 bool mutable_memory;
87 std::shared_ptr<TestMemory> test_memory;
88 std::vector<WriteRecord> write_records;
89 Common::PageTable* page_table = nullptr;
90 Kernel::KernelCore kernel;
91};
92
93} // namespace ArmTests