summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/page_table.cpp10
-rw-r--r--src/common/page_table.h68
-rw-r--r--src/common/virtual_buffer.h10
3 files changed, 65 insertions, 23 deletions
diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp
index bccea0894..8fd8620fd 100644
--- a/src/common/page_table.cpp
+++ b/src/common/page_table.cpp
@@ -10,16 +10,10 @@ PageTable::PageTable() = default;
10 10
11PageTable::~PageTable() noexcept = default; 11PageTable::~PageTable() noexcept = default;
12 12
13void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits, 13void PageTable::Resize(size_t address_space_width_in_bits, size_t page_size_in_bits) {
14 bool has_attribute) { 14 const size_t num_page_table_entries{1ULL << (address_space_width_in_bits - page_size_in_bits)};
15 const std::size_t num_page_table_entries{1ULL
16 << (address_space_width_in_bits - page_size_in_bits)};
17 pointers.resize(num_page_table_entries); 15 pointers.resize(num_page_table_entries);
18 backing_addr.resize(num_page_table_entries); 16 backing_addr.resize(num_page_table_entries);
19
20 if (has_attribute) {
21 attributes.resize(num_page_table_entries);
22 }
23} 17}
24 18
25} // namespace Common 19} // namespace Common
diff --git a/src/common/page_table.h b/src/common/page_table.h
index 9754fabf9..8d4ee9249 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -4,6 +4,7 @@
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"
@@ -20,10 +21,6 @@ enum class PageType : u8 {
20 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and 21 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and
21 /// invalidation 22 /// invalidation
22 RasterizerCachedMemory, 23 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}; 24};
28 25
29struct SpecialRegion { 26struct SpecialRegion {
@@ -48,6 +45,59 @@ struct SpecialRegion {
48 * mimics the way a real CPU page table works. 45 * mimics the way a real CPU page table works.
49 */ 46 */
50struct PageTable { 47struct PageTable {
48 /// Number of bits reserved for attribute tagging.
49 /// This can be at most the guaranteed alignment of the pointers in the page table.
50 static constexpr int ATTRIBUTE_BITS = 2;
51
52 /**
53 * Pair of host pointer and page type attribute.
54 * This uses the lower bits of a given pointer to store the attribute tag.
55 * Writing and reading the pointer attribute pair is guaranteed to be atomic for the same method
56 * call. In other words, they are guaranteed to be synchronized at all times.
57 */
58 class PageInfo {
59 public:
60 /// Returns the page pointer
61 [[nodiscard]] u8* Pointer() const noexcept {
62 return ExtractPointer(raw.load(std::memory_order_relaxed));
63 }
64
65 /// Returns the page type attribute
66 [[nodiscard]] PageType Type() const noexcept {
67 return ExtractType(raw.load(std::memory_order_relaxed));
68 }
69
70 /// Returns the page pointer and attribute pair, extracted from the same atomic read
71 [[nodiscard]] std::pair<u8*, PageType> PointerType() const noexcept {
72 const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed);
73 return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)};
74 }
75
76 /// Returns the raw representation of the page information.
77 /// Use ExtractPointer and ExtractType to unpack the value.
78 [[nodiscard]] uintptr_t Raw() const noexcept {
79 return raw.load(std::memory_order_relaxed);
80 }
81
82 /// Write a page pointer and type pair atomically
83 void Store(u8* pointer, PageType type) noexcept {
84 raw.store(reinterpret_cast<uintptr_t>(pointer) | static_cast<uintptr_t>(type));
85 }
86
87 /// Unpack a pointer from a page info raw representation
88 [[nodiscard]] static u8* ExtractPointer(uintptr_t raw) noexcept {
89 return reinterpret_cast<u8*>(raw & (~uintptr_t{0} << ATTRIBUTE_BITS));
90 }
91
92 /// Unpack a page type from a page info raw representation
93 [[nodiscard]] static PageType ExtractType(uintptr_t raw) noexcept {
94 return static_cast<PageType>(raw & ((uintptr_t{1} << ATTRIBUTE_BITS) - 1));
95 }
96
97 private:
98 std::atomic<uintptr_t> raw;
99 };
100
51 PageTable(); 101 PageTable();
52 ~PageTable() noexcept; 102 ~PageTable() noexcept;
53 103
@@ -63,20 +113,16 @@ struct PageTable {
63 * 113 *
64 * @param address_space_width_in_bits The address size width in bits. 114 * @param address_space_width_in_bits The address size width in bits.
65 * @param page_size_in_bits The page size in bits. 115 * @param page_size_in_bits The page size in bits.
66 * @param has_attribute Whether or not this page has any backing attributes.
67 */ 116 */
68 void Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits, 117 void Resize(size_t address_space_width_in_bits, size_t page_size_in_bits);
69 bool has_attribute);
70 118
71 /** 119 /**
72 * Vector of memory pointers backing each page. An entry can only be non-null if the 120 * 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`. 121 * corresponding attribute element is of type `Memory`.
74 */ 122 */
75 VirtualBuffer<u8*> pointers; 123 VirtualBuffer<PageInfo> pointers;
76 124
77 VirtualBuffer<u64> backing_addr; 125 VirtualBuffer<u64> backing_addr;
78
79 VirtualBuffer<PageType> attributes;
80}; 126};
81 127
82} // namespace Common 128} // namespace Common
diff --git a/src/common/virtual_buffer.h b/src/common/virtual_buffer.h
index 91d430036..fb1a6f81f 100644
--- a/src/common/virtual_buffer.h
+++ b/src/common/virtual_buffer.h
@@ -15,10 +15,12 @@ void FreeMemoryPages(void* base, std::size_t size) noexcept;
15template <typename T> 15template <typename T>
16class VirtualBuffer final { 16class VirtualBuffer final {
17public: 17public:
18 static_assert( 18 // TODO: Uncomment this and change Common::PageTable::PageInfo to be trivially constructible
19 std::is_trivially_constructible_v<T>, 19 // using std::atomic_ref once libc++ has support for it
20 "T must be trivially constructible, as non-trivial constructors will not be executed " 20 // static_assert(
21 "with the current allocator"); 21 // std::is_trivially_constructible_v<T>,
22 // "T must be trivially constructible, as non-trivial constructors will not be executed "
23 // "with the current allocator");
22 24
23 constexpr VirtualBuffer() = default; 25 constexpr VirtualBuffer() = default;
24 explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} { 26 explicit VirtualBuffer(std::size_t count) : alloc_size{count * sizeof(T)} {