diff options
Diffstat (limited to 'src/common/page_table.h')
| -rw-r--r-- | src/common/page_table.h | 88 |
1 files changed, 58 insertions, 30 deletions
diff --git a/src/common/page_table.h b/src/common/page_table.h index 9754fabf9..61c5552e0 100644 --- a/src/common/page_table.h +++ b/src/common/page_table.h | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | ||
| 7 | #include <tuple> | 8 | #include <tuple> |
| 8 | 9 | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | #include "common/memory_hook.h" | ||
| 11 | #include "common/virtual_buffer.h" | 11 | #include "common/virtual_buffer.h" |
| 12 | 12 | ||
| 13 | namespace Common { | 13 | namespace Common { |
| @@ -20,27 +20,6 @@ enum class PageType : u8 { | |||
| 20 | /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and | 20 | /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and |
| 21 | /// invalidation | 21 | /// invalidation |
| 22 | RasterizerCachedMemory, | 22 | RasterizerCachedMemory, |
| 23 | /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. | ||
| 24 | Special, | ||
| 25 | /// Page is allocated for use. | ||
| 26 | Allocated, | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct SpecialRegion { | ||
| 30 | enum class Type { | ||
| 31 | DebugHook, | ||
| 32 | IODevice, | ||
| 33 | } type; | ||
| 34 | |||
| 35 | MemoryHookPointer handler; | ||
| 36 | |||
| 37 | [[nodiscard]] bool operator<(const SpecialRegion& other) const { | ||
| 38 | return std::tie(type, handler) < std::tie(other.type, other.handler); | ||
| 39 | } | ||
| 40 | |||
| 41 | [[nodiscard]] bool operator==(const SpecialRegion& other) const { | ||
| 42 | return std::tie(type, handler) == std::tie(other.type, other.handler); | ||
| 43 | } | ||
| 44 | }; | 23 | }; |
| 45 | 24 | ||
| 46 | /** | 25 | /** |
| @@ -48,6 +27,59 @@ struct SpecialRegion { | |||
| 48 | * mimics the way a real CPU page table works. | 27 | * mimics the way a real CPU page table works. |
| 49 | */ | 28 | */ |
| 50 | struct PageTable { | 29 | struct PageTable { |
| 30 | /// Number of bits reserved for attribute tagging. | ||
| 31 | /// This can be at most the guaranteed alignment of the pointers in the page table. | ||
| 32 | static constexpr int ATTRIBUTE_BITS = 2; | ||
| 33 | |||
| 34 | /** | ||
| 35 | * Pair of host pointer and page type attribute. | ||
| 36 | * This uses the lower bits of a given pointer to store the attribute tag. | ||
| 37 | * Writing and reading the pointer attribute pair is guaranteed to be atomic for the same method | ||
| 38 | * call. In other words, they are guaranteed to be synchronized at all times. | ||
| 39 | */ | ||
| 40 | class PageInfo { | ||
| 41 | public: | ||
| 42 | /// Returns the page pointer | ||
| 43 | [[nodiscard]] u8* Pointer() const noexcept { | ||
| 44 | return ExtractPointer(raw.load(std::memory_order_relaxed)); | ||
| 45 | } | ||
| 46 | |||
| 47 | /// Returns the page type attribute | ||
| 48 | [[nodiscard]] PageType Type() const noexcept { | ||
| 49 | return ExtractType(raw.load(std::memory_order_relaxed)); | ||
| 50 | } | ||
| 51 | |||
| 52 | /// Returns the page pointer and attribute pair, extracted from the same atomic read | ||
| 53 | [[nodiscard]] std::pair<u8*, PageType> PointerType() const noexcept { | ||
| 54 | const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed); | ||
| 55 | return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)}; | ||
| 56 | } | ||
| 57 | |||
| 58 | /// Returns the raw representation of the page information. | ||
| 59 | /// Use ExtractPointer and ExtractType to unpack the value. | ||
| 60 | [[nodiscard]] uintptr_t Raw() const noexcept { | ||
| 61 | return raw.load(std::memory_order_relaxed); | ||
| 62 | } | ||
| 63 | |||
| 64 | /// Write a page pointer and type pair atomically | ||
| 65 | void Store(u8* pointer, PageType type) noexcept { | ||
| 66 | raw.store(reinterpret_cast<uintptr_t>(pointer) | static_cast<uintptr_t>(type)); | ||
| 67 | } | ||
| 68 | |||
| 69 | /// Unpack a pointer from a page info raw representation | ||
| 70 | [[nodiscard]] static u8* ExtractPointer(uintptr_t raw) noexcept { | ||
| 71 | return reinterpret_cast<u8*>(raw & (~uintptr_t{0} << ATTRIBUTE_BITS)); | ||
| 72 | } | ||
| 73 | |||
| 74 | /// Unpack a page type from a page info raw representation | ||
| 75 | [[nodiscard]] static PageType ExtractType(uintptr_t raw) noexcept { | ||
| 76 | return static_cast<PageType>(raw & ((uintptr_t{1} << ATTRIBUTE_BITS) - 1)); | ||
| 77 | } | ||
| 78 | |||
| 79 | private: | ||
| 80 | std::atomic<uintptr_t> raw; | ||
| 81 | }; | ||
| 82 | |||
| 51 | PageTable(); | 83 | PageTable(); |
| 52 | ~PageTable() noexcept; | 84 | ~PageTable() noexcept; |
| 53 | 85 | ||
| @@ -58,25 +90,21 @@ struct PageTable { | |||
| 58 | PageTable& operator=(PageTable&&) noexcept = default; | 90 | PageTable& operator=(PageTable&&) noexcept = default; |
| 59 | 91 | ||
| 60 | /** | 92 | /** |
| 61 | * Resizes the page table to be able to accomodate enough pages within | 93 | * Resizes the page table to be able to accommodate enough pages within |
| 62 | * a given address space. | 94 | * a given address space. |
| 63 | * | 95 | * |
| 64 | * @param address_space_width_in_bits The address size width in bits. | 96 | * @param address_space_width_in_bits The address size width in bits. |
| 65 | * @param page_size_in_bits The page size in bits. | 97 | * @param page_size_in_bits The page size in bits. |
| 66 | * @param has_attribute Whether or not this page has any backing attributes. | ||
| 67 | */ | 98 | */ |
| 68 | void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits, | 99 | void Resize(size_t address_space_width_in_bits, size_t page_size_in_bits); |
| 69 | bool has_attribute); | ||
| 70 | 100 | ||
| 71 | /** | 101 | /** |
| 72 | * Vector of memory pointers backing each page. An entry can only be non-null if the | 102 | * Vector of memory pointers backing each page. An entry can only be non-null if the |
| 73 | * corresponding entry in the `attributes` vector is of type `Memory`. | 103 | * corresponding attribute element is of type `Memory`. |
| 74 | */ | 104 | */ |
| 75 | VirtualBuffer<u8*> pointers; | 105 | VirtualBuffer<PageInfo> pointers; |
| 76 | 106 | ||
| 77 | VirtualBuffer<u64> backing_addr; | 107 | VirtualBuffer<u64> backing_addr; |
| 78 | |||
| 79 | VirtualBuffer<PageType> attributes; | ||
| 80 | }; | 108 | }; |
| 81 | 109 | ||
| 82 | } // namespace Common | 110 | } // namespace Common |