2024-03-05 21:49:07 +01:00
|
|
|
// SPDX-FileCopyrightText: 2021 suyu Emulator Project
|
2022-06-30 01:27:49 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2021-11-10 17:37:17 +01:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <type_traits>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "common/common_types.h"
|
|
|
|
|
|
|
|
namespace Common {
|
|
|
|
|
|
|
|
template <typename BaseAddr>
|
|
|
|
class MultiLevelPageTable final {
|
|
|
|
public:
|
|
|
|
constexpr MultiLevelPageTable() = default;
|
|
|
|
explicit MultiLevelPageTable(std::size_t address_space_bits, std::size_t first_level_bits,
|
|
|
|
std::size_t page_bits);
|
|
|
|
|
|
|
|
~MultiLevelPageTable() noexcept;
|
|
|
|
|
|
|
|
MultiLevelPageTable(const MultiLevelPageTable&) = delete;
|
|
|
|
MultiLevelPageTable& operator=(const MultiLevelPageTable&) = delete;
|
|
|
|
|
|
|
|
MultiLevelPageTable(MultiLevelPageTable&& other) noexcept
|
|
|
|
: address_space_bits{std::exchange(other.address_space_bits, 0)},
|
|
|
|
first_level_bits{std::exchange(other.first_level_bits, 0)}, page_bits{std::exchange(
|
|
|
|
other.page_bits, 0)},
|
|
|
|
first_level_shift{std::exchange(other.first_level_shift, 0)},
|
|
|
|
first_level_chunk_size{std::exchange(other.first_level_chunk_size, 0)},
|
|
|
|
first_level_map{std::move(other.first_level_map)}, base_ptr{std::exchange(other.base_ptr,
|
|
|
|
nullptr)} {}
|
|
|
|
|
|
|
|
MultiLevelPageTable& operator=(MultiLevelPageTable&& other) noexcept {
|
|
|
|
address_space_bits = std::exchange(other.address_space_bits, 0);
|
|
|
|
first_level_bits = std::exchange(other.first_level_bits, 0);
|
|
|
|
page_bits = std::exchange(other.page_bits, 0);
|
|
|
|
first_level_shift = std::exchange(other.first_level_shift, 0);
|
|
|
|
first_level_chunk_size = std::exchange(other.first_level_chunk_size, 0);
|
|
|
|
alloc_size = std::exchange(other.alloc_size, 0);
|
|
|
|
first_level_map = std::move(other.first_level_map);
|
|
|
|
base_ptr = std::exchange(other.base_ptr, nullptr);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReserveRange(u64 start, std::size_t size);
|
|
|
|
|
2022-09-01 05:45:22 +02:00
|
|
|
[[nodiscard]] const BaseAddr& operator[](std::size_t index) const {
|
2021-11-10 17:37:17 +01:00
|
|
|
return base_ptr[index];
|
|
|
|
}
|
|
|
|
|
2022-09-01 05:45:22 +02:00
|
|
|
[[nodiscard]] BaseAddr& operator[](std::size_t index) {
|
2021-11-10 17:37:17 +01:00
|
|
|
return base_ptr[index];
|
|
|
|
}
|
|
|
|
|
2022-09-01 05:45:22 +02:00
|
|
|
[[nodiscard]] BaseAddr* data() {
|
2021-11-10 17:37:17 +01:00
|
|
|
return base_ptr;
|
|
|
|
}
|
|
|
|
|
2022-09-01 05:45:22 +02:00
|
|
|
[[nodiscard]] const BaseAddr* data() const {
|
2021-11-10 17:37:17 +01:00
|
|
|
return base_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void AllocateLevel(u64 level);
|
|
|
|
|
|
|
|
std::size_t address_space_bits{};
|
|
|
|
std::size_t first_level_bits{};
|
|
|
|
std::size_t page_bits{};
|
|
|
|
std::size_t first_level_shift{};
|
|
|
|
std::size_t first_level_chunk_size{};
|
|
|
|
std::size_t alloc_size{};
|
|
|
|
std::vector<void*> first_level_map{};
|
|
|
|
BaseAddr* base_ptr{};
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Common
|