diff options
Diffstat (limited to 'src/common/page_table.cpp')
| -rw-r--r-- | src/common/page_table.cpp | 58 |
1 files changed, 56 insertions, 2 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 |