summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/kernel/k_page_table_slab_heap.h93
2 files changed, 94 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 457a0bfd2..199e0e69f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -224,6 +224,7 @@ add_library(core STATIC
224 hle/kernel/k_page_group.h 224 hle/kernel/k_page_group.h
225 hle/kernel/k_page_table.cpp 225 hle/kernel/k_page_table.cpp
226 hle/kernel/k_page_table.h 226 hle/kernel/k_page_table.h
227 hle/kernel/k_page_table_slab_heap.h
227 hle/kernel/k_port.cpp 228 hle/kernel/k_port.cpp
228 hle/kernel/k_port.h 229 hle/kernel/k_port.h
229 hle/kernel/k_priority_queue.h 230 hle/kernel/k_priority_queue.h
diff --git a/src/core/hle/kernel/k_page_table_slab_heap.h b/src/core/hle/kernel/k_page_table_slab_heap.h
new file mode 100644
index 000000000..a9543cbd0
--- /dev/null
+++ b/src/core/hle/kernel/k_page_table_slab_heap.h
@@ -0,0 +1,93 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7#include <vector>
8
9#include "common/common_types.h"
10#include "core/hle/kernel/k_dynamic_slab_heap.h"
11#include "core/hle/kernel/slab_helpers.h"
12
13namespace Kernel {
14
15namespace impl {
16
17class PageTablePage {
18public:
19 // Do not initialize anything.
20 PageTablePage() = default;
21
22private:
23 std::array<u8, PageSize> m_buffer{};
24};
25static_assert(sizeof(PageTablePage) == PageSize);
26
27} // namespace impl
28
29class KPageTableSlabHeap : public KDynamicSlabHeap<impl::PageTablePage, true> {
30public:
31 using RefCount = u16;
32 static constexpr size_t PageTableSize = sizeof(impl::PageTablePage);
33 static_assert(PageTableSize == PageSize);
34
35public:
36 KPageTableSlabHeap() = default;
37
38 static constexpr size_t CalculateReferenceCountSize(size_t size) {
39 return (size / PageSize) * sizeof(RefCount);
40 }
41
42 void Initialize(KDynamicPageManager* page_allocator, size_t object_count, RefCount* rc) {
43 BaseHeap::Initialize(page_allocator, object_count);
44 this->Initialize(rc);
45 }
46
47 RefCount GetRefCount(VAddr addr) {
48 ASSERT(this->IsInRange(addr));
49 return *this->GetRefCountPointer(addr);
50 }
51
52 void Open(VAddr addr, int count) {
53 ASSERT(this->IsInRange(addr));
54
55 *this->GetRefCountPointer(addr) += static_cast<RefCount>(count);
56
57 ASSERT(this->GetRefCount(addr) > 0);
58 }
59
60 bool Close(VAddr addr, int count) {
61 ASSERT(this->IsInRange(addr));
62 ASSERT(this->GetRefCount(addr) >= count);
63
64 *this->GetRefCountPointer(addr) -= static_cast<RefCount>(count);
65 return this->GetRefCount(addr) == 0;
66 }
67
68 bool IsInPageTableHeap(VAddr addr) const {
69 return this->IsInRange(addr);
70 }
71
72private:
73 void Initialize([[maybe_unused]] RefCount* rc) {
74 // TODO(bunnei): Use rc once we support kernel virtual memory allocations.
75 const auto count = this->GetSize() / PageSize;
76 m_ref_counts.resize(count);
77
78 for (size_t i = 0; i < count; i++) {
79 m_ref_counts[i] = 0;
80 }
81 }
82
83 RefCount* GetRefCountPointer(VAddr addr) {
84 return m_ref_counts.data() + ((addr - this->GetAddress()) / PageSize);
85 }
86
87private:
88 using BaseHeap = KDynamicSlabHeap<impl::PageTablePage, true>;
89
90 std::vector<RefCount> m_ref_counts;
91};
92
93} // namespace Kernel