root_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 <debug.h>
23 #include <guard_exceptions.h>
26 
27 using namespace x64;
28 
29 // -----------------------------------------------------------------------------
30 // Testing Seem
31 // -----------------------------------------------------------------------------
32 
33 #ifdef CROSS_COMPILED
34 
36 { std::terminate(); }
37 
38 #else
39 
40 auto g_terminate_called = false;
41 
43 { g_terminate_called = true; }
44 
45 #endif
46 
47 // -----------------------------------------------------------------------------
48 // Implementation
49 // -----------------------------------------------------------------------------
50 
52  m_is_vmm(is_vmm),
53  m_pt{std::make_unique<page_table_x64>(&m_cr3)}
54 { }
55 
58 { return m_cr3; }
59 
60 void
62 {
63  std::lock_guard<std::mutex> guard(m_mutex);
64  unmap_page(virt);
65 }
66 
67 void
69  integer_pointer saddr, integer_pointer eaddr)
70 {
71  expects((saddr & (page_table::pdpt::size_bytes - 1)) == 0);
72  expects((eaddr & (page_table::pdpt::size_bytes - 1)) == 0);
73 
74  for (auto virt = saddr; virt < eaddr; virt += page_table::pdpt::size_bytes)
76 }
77 
78 void
80  integer_pointer saddr, integer_pointer eaddr)
81 {
82  expects((saddr & (page_table::pd::size_bytes - 1)) == 0);
83  expects((eaddr & (page_table::pd::size_bytes - 1)) == 0);
84 
85  for (auto virt = saddr; virt < eaddr; virt += page_table::pd::size_bytes)
87 }
88 
89 void
91  integer_pointer saddr, integer_pointer eaddr)
92 {
93  expects((saddr & (page_table::pt::size_bytes - 1)) == 0);
94  expects((eaddr & (page_table::pt::size_bytes - 1)) == 0);
95 
96  for (auto virt = saddr; virt < eaddr; virt += page_table::pt::size_bytes)
98 }
99 
100 void
102  integer_pointer saddr, integer_pointer eaddr)
103 {
104  expects((saddr & (page_table::pdpt::size_bytes - 1)) == 0);
105  expects((eaddr & (page_table::pdpt::size_bytes - 1)) == 0);
106 
107  for (auto virt = saddr; virt < eaddr; virt += page_table::pdpt::size_bytes)
108  this->unmap(virt);
109 }
110 
111 void
113  integer_pointer saddr, integer_pointer eaddr)
114 {
115  expects((saddr & (page_table::pd::size_bytes - 1)) == 0);
116  expects((eaddr & (page_table::pd::size_bytes - 1)) == 0);
117 
118  for (auto virt = saddr; virt < eaddr; virt += page_table::pd::size_bytes)
119  this->unmap(virt);
120 }
121 
122 void
124  integer_pointer saddr, integer_pointer eaddr)
125 {
126  expects((saddr & (page_table::pt::size_bytes - 1)) == 0);
127  expects((eaddr & (page_table::pt::size_bytes - 1)) == 0);
128 
129  for (auto virt = saddr; virt < eaddr; virt += page_table::pt::size_bytes)
130  this->unmap(virt);
131 }
132 
135 {
136  std::lock_guard<std::mutex> guard(m_mutex);
137  return m_pt->virt_to_pte(virt);
138 }
139 
142 {
143  std::lock_guard<std::mutex> guard(m_mutex);
144  return m_pt->pt_to_mdl();
145 }
146 
148 root_page_table_x64::add_page(integer_pointer virt, size_type size)
149 {
150  switch (size)
151  {
153  return m_pt->add_page_1g(virt);
154 
156  return m_pt->add_page_2m(virt);
157 
159  return m_pt->add_page_4k(virt);
160 
161  default:
162  throw std::logic_error("invalid pt size");
163  }
164 }
165 
166 void
167 root_page_table_x64::map_page(integer_pointer virt, integer_pointer phys, attr_type attr, size_type size)
168 {
169  std::lock_guard<std::mutex> guard(m_mutex);
170 
171  auto &&entry = add_page(virt, size);
172 
173  auto ___ = gsl::on_failure([&]
174  { this->unmap_page(virt); });
175 
176  switch (size)
177  {
179  entry.clear();
180  entry.set_phys_addr(phys & ~(page_table::pdpt::size_bytes - 1));
181  entry.set_present(true);
182  entry.set_ps(true);
183  entry.set_pat_index_large(pat::mem_attr_to_pat_index(attr));
184  break;
185 
187  entry.clear();
188  entry.set_phys_addr(phys & ~(page_table::pd::size_bytes - 1));
189  entry.set_present(true);
190  entry.set_ps(true);
191  entry.set_pat_index_large(pat::mem_attr_to_pat_index(attr));
192  break;
193 
195  entry.clear();
196  entry.set_phys_addr(phys & ~(page_table::pt::size_bytes - 1));
197  entry.set_present(true);
198  entry.set_pat_index_4k(pat::mem_attr_to_pat_index(attr));
199  break;
200  }
201 
202  switch (attr)
203  {
204  case memory_attr::rw_uc:
205  case memory_attr::rw_wc:
206  case memory_attr::rw_wt:
207  case memory_attr::rw_wp:
208  case memory_attr::rw_wb:
210  entry.set_rw(true);
211  entry.set_nx(true);
212  break;
213 
214  case memory_attr::re_uc:
215  case memory_attr::re_wc:
216  case memory_attr::re_wt:
217  case memory_attr::re_wp:
218  case memory_attr::re_wb:
220  entry.set_rw(false);
221  entry.set_nx(false);
222  break;
223 
224  case memory_attr::pt_uc:
225  case memory_attr::pt_wc:
226  case memory_attr::pt_wt:
227  case memory_attr::pt_wp:
228  case memory_attr::pt_wb:
230  entry.set_rw(true);
231  entry.set_nx(false);
232  break;
233 
234  default:
235  throw std::logic_error("unsupported memory permissions");
236  }
237 
238  if (m_is_vmm)
239  g_mm->add_md(virt, phys, attr);
240 }
241 
242 void
243 root_page_table_x64::unmap_page(integer_pointer virt) noexcept
244 {
245  guard_exceptions([&]
246  { m_pt->remove_page(virt); });
247 
248  if (m_is_vmm)
249  {
250  guard_exceptions([&]
251  { g_mm->remove_md(virt); });
252  }
253 }
254 
257 {
258  static std::unique_ptr<root_page_table_x64> rpt;
259 
260  if (!rpt)
261  {
262  rpt = std::make_unique<root_page_table_x64>(true);
263 
264  try
265  {
266  for (const auto &md : g_mm->descriptors())
267  {
268  auto attr = memory_attr::invalid;
269 
270  if (md.type == (MEMORY_TYPE_R | MEMORY_TYPE_W))
271  attr = memory_attr::rw_wb;
272  if (md.type == (MEMORY_TYPE_R | MEMORY_TYPE_E))
273  attr = memory_attr::re_wb;
274 
275  rpt->map_4k(md.virt, md.phys, attr);
276  }
277  }
278  catch (std::exception &e)
279  {
280  rpt.reset();
281 
282  bferror << "failed to construct root page tables: " << e.what() << bfendl;
284  }
285  }
286 
287  return rpt.get();
288 }
constexpr const auto pt_wp
Definition: mem_attr_x64.h:60
virtual void map_2m(integer_pointer virt, integer_pointer phys, attr_type attr)
expects(rbx)
constexpr const auto re_wc
Definition: mem_attr_x64.h:51
#define MEMORY_TYPE_E
Definition: memory.h:41
#define MEMORY_TYPE_W
Definition: memory.h:40
virtual void map_1g(integer_pointer virt, integer_pointer phys, attr_type attr)
constexpr const auto re_wp
Definition: mem_attr_x64.h:53
void unmap_identity_map_1g(integer_pointer saddr, integer_pointer eaddr)
constexpr const auto re_uc_m
Definition: mem_attr_x64.h:55
void root_page_table_terminate()
constexpr const auto rw_uc_m
Definition: mem_attr_x64.h:48
void setup_identity_map_1g(integer_pointer saddr, integer_pointer eaddr)
root_page_table_x64 * root_pt() noexcept
constexpr const auto invalid
Definition: mem_attr_x64.h:37
auto mem_attr_to_pat_index(T attr)
Definition: pat_x64.h:61
constexpr const auto pt_wb
Definition: mem_attr_x64.h:61
#define MEMORY_TYPE_R
Definition: memory.h:39
constexpr const auto size_bytes
page_table_x64::memory_descriptor_list memory_descriptor_list
constexpr const auto size
constexpr const auto re_wt
Definition: mem_attr_x64.h:52
void uint64_t uint64_t uint64_t *rdx noexcept
virtual void map_4k(integer_pointer virt, integer_pointer phys, attr_type attr)
virtual void unmap(integer_pointer virt) noexcept
constexpr const auto rw_wb
Definition: mem_attr_x64.h:47
memory_descriptor_list pt_to_mdl() const
uint64_t attr_type
Definition: mem_attr_x64.h:35
void unmap_identity_map_2m(integer_pointer saddr, integer_pointer eaddr)
virtual cr3_type cr3()
constexpr const auto rw_uc
Definition: mem_attr_x64.h:43
uint32_t size_type
Definition: portio_x64.h:62
constexpr const auto pt_wt
Definition: mem_attr_x64.h:59
constexpr const auto re_uc
Definition: mem_attr_x64.h:50
constexpr const auto pt_wc
Definition: mem_attr_x64.h:58
constexpr const auto pt_uc
Definition: mem_attr_x64.h:57
constexpr page_table_x64::integer_pointer virt
uintptr_t integer_pointer
Definition: cache_x64.h:36
#define g_mm
constexpr const auto rw_wc
Definition: mem_attr_x64.h:44
void setup_identity_map_4k(integer_pointer saddr, integer_pointer eaddr)
constexpr const auto pt_uc_m
Definition: mem_attr_x64.h:62
page_table_entry_x64 virt_to_pte(integer_pointer virt) const
E guard_exceptions(E error_code, T func)
void setup_identity_map_2m(integer_pointer saddr, integer_pointer eaddr)
constexpr const auto rw_wt
Definition: mem_attr_x64.h:45
auto g_terminate_called
Definition: cache_x64.h:31
constexpr const auto rw_wp
Definition: mem_attr_x64.h:46
root_page_table_x64(bool is_vmm=false)
constexpr const auto re_wb
Definition: mem_attr_x64.h:54
void unmap_identity_map_4k(integer_pointer saddr, integer_pointer eaddr)