summaryrefslogtreecommitdiff
path: root/src/common/page_table.h
diff options
context:
space:
mode:
authorGravatar Levi2021-01-10 22:09:56 -0700
committerGravatar Levi2021-01-10 22:09:56 -0700
commit7a3c884e39fccfbb498b855080bffabc9ce2e7f1 (patch)
tree5056f9406dec188439cb0deb87603498243a9412 /src/common/page_table.h
parentMore forgetting... duh (diff)
parentMerge pull request #5229 from Morph1984/fullscreen-opt (diff)
downloadyuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.gz
yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.tar.xz
yuzu-7a3c884e39fccfbb498b855080bffabc9ce2e7f1.zip
Merge remote-tracking branch 'upstream/master' into int-flags
Diffstat (limited to 'src/common/page_table.h')
-rw-r--r--src/common/page_table.h100
1 files changed, 67 insertions, 33 deletions
diff --git a/src/common/page_table.h b/src/common/page_table.h
index cf5eed780..61c5552e0 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -4,12 +4,10 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <vector> 7#include <atomic>
8 8#include <tuple>
9#include <boost/icl/interval_map.hpp>
10 9
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "common/memory_hook.h"
13#include "common/virtual_buffer.h" 11#include "common/virtual_buffer.h"
14 12
15namespace Common { 13namespace Common {
@@ -22,27 +20,6 @@ enum class PageType : u8 {
22 /// 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
23 /// invalidation 21 /// invalidation
24 RasterizerCachedMemory, 22 RasterizerCachedMemory,
25 /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions.
26 Special,
27 /// Page is allocated for use.
28 Allocated,
29};
30
31struct SpecialRegion {
32 enum class Type {
33 DebugHook,
34 IODevice,
35 } type;
36
37 MemoryHookPointer handler;
38
39 [[nodiscard]] bool operator<(const SpecialRegion& other) const {
40 return std::tie(type, handler) < std::tie(other.type, other.handler);
41 }
42
43 [[nodiscard]] bool operator==(const SpecialRegion& other) const {
44 return std::tie(type, handler) == std::tie(other.type, other.handler);
45 }
46}; 23};
47 24
48/** 25/**
@@ -50,27 +27,84 @@ struct SpecialRegion {
50 * mimics the way a real CPU page table works. 27 * mimics the way a real CPU page table works.
51 */ 28 */
52struct 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
53 PageTable(); 83 PageTable();
54 ~PageTable(); 84 ~PageTable() noexcept;
85
86 PageTable(const PageTable&) = delete;
87 PageTable& operator=(const PageTable&) = delete;
88
89 PageTable(PageTable&&) noexcept = default;
90 PageTable& operator=(PageTable&&) noexcept = default;
55 91
56 /** 92 /**
57 * 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
58 * a given address space. 94 * a given address space.
59 * 95 *
60 * @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.
97 * @param page_size_in_bits The page size in bits.
61 */ 98 */
62 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);
63 bool has_attribute);
64 100
65 /** 101 /**
66 * 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
67 * corresponding entry in the `attributes` vector is of type `Memory`. 103 * corresponding attribute element is of type `Memory`.
68 */ 104 */
69 VirtualBuffer<u8*> pointers; 105 VirtualBuffer<PageInfo> pointers;
70 106
71 VirtualBuffer<u64> backing_addr; 107 VirtualBuffer<u64> backing_addr;
72
73 VirtualBuffer<PageType> attributes;
74}; 108};
75 109
76} // namespace Common 110} // namespace Common