summaryrefslogtreecommitdiff
path: root/src/common/multi_level_page_table.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/multi_level_page_table.h')
-rw-r--r--src/common/multi_level_page_table.h78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/common/multi_level_page_table.h b/src/common/multi_level_page_table.h
new file mode 100644
index 000000000..31f6676a0
--- /dev/null
+++ b/src/common/multi_level_page_table.h
@@ -0,0 +1,78 @@
1// SPDX-FileCopyrightText: 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <type_traits>
7#include <utility>
8#include <vector>
9
10#include "common/common_types.h"
11
12namespace Common {
13
14template <typename BaseAddr>
15class MultiLevelPageTable final {
16public:
17 constexpr MultiLevelPageTable() = default;
18 explicit MultiLevelPageTable(std::size_t address_space_bits, std::size_t first_level_bits,
19 std::size_t page_bits);
20
21 ~MultiLevelPageTable() noexcept;
22
23 MultiLevelPageTable(const MultiLevelPageTable&) = delete;
24 MultiLevelPageTable& operator=(const MultiLevelPageTable&) = delete;
25
26 MultiLevelPageTable(MultiLevelPageTable&& other) noexcept
27 : address_space_bits{std::exchange(other.address_space_bits, 0)},
28 first_level_bits{std::exchange(other.first_level_bits, 0)}, page_bits{std::exchange(
29 other.page_bits, 0)},
30 first_level_shift{std::exchange(other.first_level_shift, 0)},
31 first_level_chunk_size{std::exchange(other.first_level_chunk_size, 0)},
32 first_level_map{std::move(other.first_level_map)}, base_ptr{std::exchange(other.base_ptr,
33 nullptr)} {}
34
35 MultiLevelPageTable& operator=(MultiLevelPageTable&& other) noexcept {
36 address_space_bits = std::exchange(other.address_space_bits, 0);
37 first_level_bits = std::exchange(other.first_level_bits, 0);
38 page_bits = std::exchange(other.page_bits, 0);
39 first_level_shift = std::exchange(other.first_level_shift, 0);
40 first_level_chunk_size = std::exchange(other.first_level_chunk_size, 0);
41 alloc_size = std::exchange(other.alloc_size, 0);
42 first_level_map = std::move(other.first_level_map);
43 base_ptr = std::exchange(other.base_ptr, nullptr);
44 return *this;
45 }
46
47 void ReserveRange(u64 start, std::size_t size);
48
49 [[nodiscard]] const BaseAddr& operator[](std::size_t index) const {
50 return base_ptr[index];
51 }
52
53 [[nodiscard]] BaseAddr& operator[](std::size_t index) {
54 return base_ptr[index];
55 }
56
57 [[nodiscard]] BaseAddr* data() {
58 return base_ptr;
59 }
60
61 [[nodiscard]] const BaseAddr* data() const {
62 return base_ptr;
63 }
64
65private:
66 void AllocateLevel(u64 level);
67
68 std::size_t address_space_bits{};
69 std::size_t first_level_bits{};
70 std::size_t page_bits{};
71 std::size_t first_level_shift{};
72 std::size_t first_level_chunk_size{};
73 std::size_t alloc_size{};
74 std::vector<void*> first_level_map{};
75 BaseAddr* base_ptr{};
76};
77
78} // namespace Common