page_table_x64.cpp
Go to the documentation of this file.
1 //
2 // Bareflank Hypervisor
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 #include <memory_manager/pat_x64.h>
25 
26 #include <intrinsics/x64.h>
27 using namespace x64;
28 
29 page_table_x64::page_table_x64(gsl::not_null<pointer> pte)
30 {
31  m_pt = std::make_unique<integer_pointer[]>(page_table::num_entries);
32 
33  auto &&entry = page_table_entry_x64(pte);
34  entry.clear();
35  entry.set_phys_addr(g_mm->virtptr_to_physint(m_pt.get()));
36  entry.set_present(true);
37  entry.set_rw(true);
38  entry.set_pat_index_4k(pat::write_back_index);
39 }
40 
42 page_table_x64::add_page(integer_pointer addr, integer_pointer bits, integer_pointer end)
43 {
44  auto &&index = page_table::index(addr, bits);
45 
46  if (bits > end)
47  {
48  if (m_pts.empty())
49  m_pts = std::vector<std::unique_ptr<page_table_x64>>(page_table::num_entries);
50 
51  auto &&iter = bfn::find(m_pts, index);
52  if (!(*iter))
53  {
54  auto &&view = gsl::make_span(m_pt, page_table::num_entries);
55  (*iter) = std::make_unique<page_table_x64>(&view.at(index));
56  }
57 
58  return (*iter)->add_page(addr, bits - page_table::pt::size, end);
59  }
60 
61  if (!m_pts.empty())
62  {
63  m_pts.clear();
64  m_pts.shrink_to_fit();
65  }
66 
67  auto &&view = gsl::make_span(m_pt, page_table::num_entries);
68  return page_table_entry_x64(&view.at(index));
69 }
70 
71 void
73 {
74  auto &&index = page_table::index(addr, bits);
75 
76  if (!m_pts.empty())
77  {
78  auto &&iter = bfn::find(m_pts, index);
79  if (auto pt = (*iter).get())
80  {
81  pt->remove_page(addr, bits - page_table::pt::size);
82  if (pt->empty())
83  {
84  (*iter) = nullptr;
85 
86  auto &&view = gsl::make_span(m_pt, page_table::num_entries);
87  view.at(index) = 0;
88  }
89  }
90  }
91  else
92  {
93  auto &&view = gsl::make_span(m_pt, page_table::num_entries);
94  view.at(index) = 0;
95 
96  return;
97  }
98 }
99 
102 {
103  auto &&index = page_table::index(addr, bits);
104 
105  if (!m_pts.empty())
106  {
107  auto &&iter = bfn::cfind(m_pts, index);
108  if (auto pt = (*iter).get())
109  return pt->virt_to_pte(addr, bits - page_table::pt::size);
110 
111  throw std::runtime_error("unable to locate pte. invalid address");
112  }
113 
114  auto &&view = gsl::make_span(m_pt, page_table::num_entries);
115  return page_table_entry_x64(&view.at(index));
116 }
117 
119 page_table_x64::pt_to_mdl(memory_descriptor_list &mdl) const
120 {
121  auto &&virt = reinterpret_cast<uintptr_t>(m_pt.get());
122  auto &&phys = g_mm->virtint_to_physint(virt);
123  auto &&type = MEMORY_TYPE_R | MEMORY_TYPE_W;
124 
125  mdl.push_back({phys, virt, type});
126 
127  for (const auto &pt : m_pts)
128  if (pt != nullptr) pt->pt_to_mdl(mdl);
129 
130  return mdl;
131 }
132 
133 bool
134 page_table_x64::empty() const noexcept
135 {
136  auto size = 0UL;
137 
138  auto &&view = gsl::make_span(m_pt, x64::page_table::num_entries);
139  for (auto element : view)
140  size += element != 0 ? 1U : 0U;
141 
142  return size == 0;
143 }
144 
146 page_table_x64::global_size() const noexcept
147 {
148  auto size = 0UL;
149 
150  auto &&view = gsl::make_span(m_pt, x64::page_table::num_entries);
151  for (auto element : view)
152  size += element != 0 ? 1U : 0U;
153 
154  for (const auto &pt : m_pts)
155  if (pt != nullptr) size += pt->global_size();
156 
157  return size;
158 }
159 
161 page_table_x64::global_capacity() const noexcept
162 {
163  auto size = m_pts.capacity();
164 
165  for (const auto &pt : m_pts)
166  if (pt != nullptr) size += pt->global_capacity();
167 
168  return size;
169 }
page_table_x64(gsl::not_null< pointer > pte)
std::vector< memory_descriptor > memory_descriptor_list
constexpr const auto num_entries
page_table_entry_x64 virt_to_pte(integer_pointer addr) const
#define MEMORY_TYPE_W
Definition: memory.h:40
void remove_page(integer_pointer addr)
memory_descriptor_list pt_to_mdl() const
constexpr const auto size
#define MEMORY_TYPE_R
Definition: memory.h:39
constexpr const auto pt
Definition: mem_attr_x64.h:41
constexpr const auto size
void uint64_t uint64_t uint64_t *rdx noexcept
auto index(const T virt, const F from)
constexpr const auto addr
Definition: cpuid_x64.h:80
constexpr page_table_x64::integer_pointer virt
uintptr_t integer_pointer
Definition: cache_x64.h:36
#define g_mm
constexpr const auto write_back_index
Definition: pat_x64.h:57
auto end(reversed_container< T > container) -> decltype(container.container.rend())
Definition: reverse.h:43
std::size_t size_type
Definition: cache_x64.h:31