diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/page_table.cpp | 58 | ||||
| -rw-r--r-- | src/common/page_table.h | 24 |
2 files changed, 76 insertions, 6 deletions
diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp index 9fffd816f..4817b09f9 100644 --- a/src/common/page_table.cpp +++ b/src/common/page_table.cpp | |||
| @@ -10,11 +10,65 @@ PageTable::PageTable() = default; | |||
| 10 | 10 | ||
| 11 | PageTable::~PageTable() noexcept = default; | 11 | PageTable::~PageTable() noexcept = default; |
| 12 | 12 | ||
| 13 | void PageTable::Resize(size_t address_space_width_in_bits, size_t page_size_in_bits) { | 13 | bool PageTable::BeginTraversal(TraversalEntry& out_entry, TraversalContext& out_context, |
| 14 | const size_t num_page_table_entries{1ULL << (address_space_width_in_bits - page_size_in_bits)}; | 14 | u64 address) const { |
| 15 | // Setup invalid defaults. | ||
| 16 | out_entry.phys_addr = 0; | ||
| 17 | out_entry.block_size = page_size; | ||
| 18 | out_context.next_page = 0; | ||
| 19 | |||
| 20 | // Validate that we can read the actual entry. | ||
| 21 | const auto page = address / page_size; | ||
| 22 | if (page >= backing_addr.size()) { | ||
| 23 | return false; | ||
| 24 | } | ||
| 25 | |||
| 26 | // Validate that the entry is mapped. | ||
| 27 | const auto phys_addr = backing_addr[page]; | ||
| 28 | if (phys_addr == 0) { | ||
| 29 | return false; | ||
| 30 | } | ||
| 31 | |||
| 32 | // Populate the results. | ||
| 33 | out_entry.phys_addr = phys_addr + address; | ||
| 34 | out_context.next_page = page + 1; | ||
| 35 | out_context.next_offset = address + page_size; | ||
| 36 | |||
| 37 | return true; | ||
| 38 | } | ||
| 39 | |||
| 40 | bool PageTable::ContinueTraversal(TraversalEntry& out_entry, TraversalContext& context) const { | ||
| 41 | // Setup invalid defaults. | ||
| 42 | out_entry.phys_addr = 0; | ||
| 43 | out_entry.block_size = page_size; | ||
| 44 | |||
| 45 | // Validate that we can read the actual entry. | ||
| 46 | const auto page = context.next_page; | ||
| 47 | if (page >= backing_addr.size()) { | ||
| 48 | return false; | ||
| 49 | } | ||
| 50 | |||
| 51 | // Validate that the entry is mapped. | ||
| 52 | const auto phys_addr = backing_addr[page]; | ||
| 53 | if (phys_addr == 0) { | ||
| 54 | return false; | ||
| 55 | } | ||
| 56 | |||
| 57 | // Populate the results. | ||
| 58 | out_entry.phys_addr = phys_addr + context.next_offset; | ||
| 59 | context.next_page = page + 1; | ||
| 60 | context.next_offset += page_size; | ||
| 61 | |||
| 62 | return true; | ||
| 63 | } | ||
| 64 | |||
| 65 | void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits) { | ||
| 66 | const std::size_t num_page_table_entries{1ULL | ||
| 67 | << (address_space_width_in_bits - page_size_in_bits)}; | ||
| 15 | pointers.resize(num_page_table_entries); | 68 | pointers.resize(num_page_table_entries); |
| 16 | backing_addr.resize(num_page_table_entries); | 69 | backing_addr.resize(num_page_table_entries); |
| 17 | current_address_space_width_in_bits = address_space_width_in_bits; | 70 | current_address_space_width_in_bits = address_space_width_in_bits; |
| 71 | page_size = 1ULL << page_size_in_bits; | ||
| 18 | } | 72 | } |
| 19 | 73 | ||
| 20 | } // namespace Common | 74 | } // namespace Common |
diff --git a/src/common/page_table.h b/src/common/page_table.h index 8267e8b4d..82d91e9f3 100644 --- a/src/common/page_table.h +++ b/src/common/page_table.h | |||
| @@ -27,6 +27,16 @@ enum class PageType : u8 { | |||
| 27 | * mimics the way a real CPU page table works. | 27 | * mimics the way a real CPU page table works. |
| 28 | */ | 28 | */ |
| 29 | struct PageTable { | 29 | struct PageTable { |
| 30 | struct TraversalEntry { | ||
| 31 | u64 phys_addr{}; | ||
| 32 | std::size_t block_size{}; | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct TraversalContext { | ||
| 36 | u64 next_page{}; | ||
| 37 | u64 next_offset{}; | ||
| 38 | }; | ||
| 39 | |||
| 30 | /// Number of bits reserved for attribute tagging. | 40 | /// Number of bits reserved for attribute tagging. |
| 31 | /// This can be at most the guaranteed alignment of the pointers in the page table. | 41 | /// This can be at most the guaranteed alignment of the pointers in the page table. |
| 32 | static constexpr int ATTRIBUTE_BITS = 2; | 42 | static constexpr int ATTRIBUTE_BITS = 2; |
| @@ -89,6 +99,10 @@ struct PageTable { | |||
| 89 | PageTable(PageTable&&) noexcept = default; | 99 | PageTable(PageTable&&) noexcept = default; |
| 90 | PageTable& operator=(PageTable&&) noexcept = default; | 100 | PageTable& operator=(PageTable&&) noexcept = default; |
| 91 | 101 | ||
| 102 | bool BeginTraversal(TraversalEntry& out_entry, TraversalContext& out_context, | ||
| 103 | u64 address) const; | ||
| 104 | bool ContinueTraversal(TraversalEntry& out_entry, TraversalContext& context) const; | ||
| 105 | |||
| 92 | /** | 106 | /** |
| 93 | * Resizes the page table to be able to accommodate enough pages within | 107 | * Resizes the page table to be able to accommodate enough pages within |
| 94 | * a given address space. | 108 | * a given address space. |
| @@ -96,9 +110,9 @@ struct PageTable { | |||
| 96 | * @param address_space_width_in_bits The address size width in bits. | 110 | * @param address_space_width_in_bits The address size width in bits. |
| 97 | * @param page_size_in_bits The page size in bits. | 111 | * @param page_size_in_bits The page size in bits. |
| 98 | */ | 112 | */ |
| 99 | void Resize(size_t address_space_width_in_bits, size_t page_size_in_bits); | 113 | void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits); |
| 100 | 114 | ||
| 101 | size_t GetAddressSpaceBits() const { | 115 | std::size_t GetAddressSpaceBits() const { |
| 102 | return current_address_space_width_in_bits; | 116 | return current_address_space_width_in_bits; |
| 103 | } | 117 | } |
| 104 | 118 | ||
| @@ -110,9 +124,11 @@ struct PageTable { | |||
| 110 | 124 | ||
| 111 | VirtualBuffer<u64> backing_addr; | 125 | VirtualBuffer<u64> backing_addr; |
| 112 | 126 | ||
| 113 | size_t current_address_space_width_in_bits; | 127 | std::size_t current_address_space_width_in_bits{}; |
| 128 | |||
| 129 | u8* fastmem_arena{}; | ||
| 114 | 130 | ||
| 115 | u8* fastmem_arena; | 131 | std::size_t page_size{}; |
| 116 | }; | 132 | }; |
| 117 | 133 | ||
| 118 | } // namespace Common | 134 | } // namespace Common |