summaryrefslogtreecommitdiff
path: root/src/common/page_table.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/page_table.h')
-rw-r--r--src/common/page_table.h88
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
13namespace Common { 13namespace 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
29struct 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 */
50struct PageTable { 29struct 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