common: page_table: Update to use VirtualBuffer and simplify.

merge-requests/60/head
bunnei 2020-04-08 22:49:51 +07:00
parent 1d5923e150
commit 4c1812ae37
2 changed files with 18 additions and 53 deletions

@ -6,36 +6,20 @@
namespace Common {
PageTable::PageTable(std::size_t page_size_in_bits) : page_size_in_bits{page_size_in_bits} {}
PageTable::PageTable() = default;
PageTable::~PageTable() = default;
void PageTable::Resize(std::size_t address_space_width_in_bits) {
const std::size_t num_page_table_entries = 1ULL
<< (address_space_width_in_bits - page_size_in_bits);
void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits,
bool has_attribute) {
const std::size_t num_page_table_entries{1ULL
<< (address_space_width_in_bits - page_size_in_bits)};
pointers.resize(num_page_table_entries);
attributes.resize(num_page_table_entries);
// The default is a 39-bit address space, which causes an initial 1GB allocation size. If the
// vector size is subsequently decreased (via resize), the vector might not automatically
// actually reallocate/resize its underlying allocation, which wastes up to ~800 MB for
// 36-bit titles. Call shrink_to_fit to reduce capacity to what's actually in use.
pointers.shrink_to_fit();
attributes.shrink_to_fit();
}
BackingPageTable::BackingPageTable(std::size_t page_size_in_bits) : PageTable{page_size_in_bits} {}
BackingPageTable::~BackingPageTable() = default;
void BackingPageTable::Resize(std::size_t address_space_width_in_bits) {
PageTable::Resize(address_space_width_in_bits);
const std::size_t num_page_table_entries = 1ULL
<< (address_space_width_in_bits - page_size_in_bits);
backing_addr.resize(num_page_table_entries);
backing_addr.shrink_to_fit();
if (has_attribute) {
attributes.resize(num_page_table_entries);
}
}
} // namespace Common

@ -5,9 +5,12 @@
#pragma once
#include <vector>
#include <boost/icl/interval_map.hpp>
#include "common/common_types.h"
#include "common/memory_hook.h"
#include "common/virtual_buffer.h"
namespace Common {
@ -47,7 +50,7 @@ struct SpecialRegion {
* mimics the way a real CPU page table works.
*/
struct PageTable {
explicit PageTable(std::size_t page_size_in_bits);
PageTable();
~PageTable();
/**
@ -56,40 +59,18 @@ struct PageTable {
*
* @param address_space_width_in_bits The address size width in bits.
*/
void Resize(std::size_t address_space_width_in_bits);
void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits,
bool has_attribute);
/**
* Vector of memory pointers backing each page. An entry can only be non-null if the
* corresponding entry in the `attributes` vector is of type `Memory`.
*/
std::vector<u8*> pointers;
VirtualBuffer<u8*> pointers;
/**
* Contains MMIO handlers that back memory regions whose entries in the `attribute` vector is
* of type `Special`.
*/
boost::icl::interval_map<u64, std::set<SpecialRegion>> special_regions;
VirtualBuffer<u64> backing_addr;
/**
* Vector of fine grained page attributes. If it is set to any value other than `Memory`, then
* the corresponding entry in `pointers` MUST be set to null.
*/
std::vector<PageType> attributes;
const std::size_t page_size_in_bits{};
};
/**
* A more advanced Page Table with the ability to save a backing address when using it
* depends on another MMU.
*/
struct BackingPageTable : PageTable {
explicit BackingPageTable(std::size_t page_size_in_bits);
~BackingPageTable();
void Resize(std::size_t address_space_width_in_bits);
std::vector<u64> backing_addr;
VirtualBuffer<PageType> attributes;
};
} // namespace Common