test_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 <test.h>
23 #include <memory_manager/pat_x64.h>
26 
27 extern bool g_terminate_called;
28 
29 static auto
30 setup_mm(MockRepository &mocks)
31 {
32  auto descriptor_list =
33  {
34  memory_descriptor{0x12345000, 0x54321000, MEMORY_TYPE_R | MEMORY_TYPE_W},
35  memory_descriptor{0x12346000, 0x54322000, MEMORY_TYPE_R | MEMORY_TYPE_E},
36  };
37 
38  auto mm = mocks.Mock<memory_manager_x64>();
39  mocks.OnCallFunc(memory_manager_x64::instance).Return(mm);
40 
41  mocks.OnCall(mm, memory_manager_x64::descriptors).Return(descriptor_list);
42  mocks.OnCall(mm, memory_manager_x64::virtptr_to_physint).Return(0x0000000ABCDEF0000);
43  mocks.OnCall(mm, memory_manager_x64::virtint_to_physint).Return(0x0000000ABCDEF0000);
44  mocks.OnCall(mm, memory_manager_x64::add_md);
45  mocks.OnCall(mm, memory_manager_x64::remove_md);
46 
47  return mm;
48 }
49 
50 void
51 memory_manager_ut::test_root_page_table_x64_init_failure()
52 {
53  MockRepository mocks;
54  auto &&mm = setup_mm(mocks);
55 
56  mocks.OnCall(mm, memory_manager_x64::add_md).With(0x54321000, _, _).Throw(std::runtime_error("error"));
57 
58  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
59  {
60  this->expect_no_exception([&] { root_pt(); });
62  });
63 }
64 
65 void
66 memory_manager_ut::test_root_page_table_x64_init_success()
67 {
68  MockRepository mocks;
69  setup_mm(mocks);
70 
71  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
72  {
73  this->expect_no_exception([&] { root_pt(); });
74  });
75 }
76 
77 void
78 memory_manager_ut::test_root_page_table_x64_cr3()
79 {
80  MockRepository mocks;
81  setup_mm(mocks);
82  auto &&root_cr3 = root_page_table_x64{};
83 
84  this->expect_true(root_cr3.cr3() == 0x0000000ABCDEF001B);
85 }
86 
87 void
88 memory_manager_ut::test_root_page_table_x64_map_1g()
89 {
90  MockRepository mocks;
91  setup_mm(mocks);
92  auto &&root_cr3 = root_page_table_x64{};
93 
94  // Read / Write
95  {
96  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::rw_uc);
97  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
98  this->expect_true(entry.rw());
99  this->expect_true(entry.nx());
100  this->expect_true(entry.pat_index_large() == 0);
101  root_cr3.unmap(0x1000UL);
102  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
103  }
104 
105  {
106  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::rw_wc);
107  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
108  this->expect_true(entry.rw());
109  this->expect_true(entry.nx());
110  this->expect_true(entry.pat_index_large() == 1);
111  root_cr3.unmap(0x1000UL);
112  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
113  }
114 
115  {
116  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::rw_wt);
117  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
118  this->expect_true(entry.rw());
119  this->expect_true(entry.nx());
120  this->expect_true(entry.pat_index_large() == 2);
121  root_cr3.unmap(0x1000UL);
122  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
123  }
124 
125  {
126  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::rw_wp);
127  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
128  this->expect_true(entry.rw());
129  this->expect_true(entry.nx());
130  this->expect_true(entry.pat_index_large() == 5);
131  root_cr3.unmap(0x1000UL);
132  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
133  }
134 
135  {
136  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::rw_wb);
137  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
138  this->expect_true(entry.rw());
139  this->expect_true(entry.nx());
140  this->expect_true(entry.pat_index_large() == 3);
141  root_cr3.unmap(0x1000UL);
142  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
143  }
144 
145  {
146  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::rw_uc_m);
147  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
148  this->expect_true(entry.rw());
149  this->expect_true(entry.nx());
150  this->expect_true(entry.pat_index_large() == 7);
151  root_cr3.unmap(0x1000UL);
152  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
153  }
154 
155  // Read / Execute
156  {
157  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::re_uc);
158  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
159  this->expect_false(entry.rw());
160  this->expect_false(entry.nx());
161  this->expect_true(entry.pat_index_large() == 0);
162  root_cr3.unmap(0x1000UL);
163  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
164  }
165 
166  {
167  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::re_wc);
168  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
169  this->expect_false(entry.rw());
170  this->expect_false(entry.nx());
171  this->expect_true(entry.pat_index_large() == 1);
172  root_cr3.unmap(0x1000UL);
173  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
174  }
175 
176  {
177  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::re_wt);
178  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
179  this->expect_false(entry.rw());
180  this->expect_false(entry.nx());
181  this->expect_true(entry.pat_index_large() == 2);
182  root_cr3.unmap(0x1000UL);
183  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
184  }
185 
186  {
187  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::re_wp);
188  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
189  this->expect_false(entry.rw());
190  this->expect_false(entry.nx());
191  this->expect_true(entry.pat_index_large() == 5);
192  root_cr3.unmap(0x1000UL);
193  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
194  }
195 
196  {
197  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::re_wb);
198  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
199  this->expect_false(entry.rw());
200  this->expect_false(entry.nx());
201  this->expect_true(entry.pat_index_large() == 3);
202  root_cr3.unmap(0x1000UL);
203  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
204  }
205 
206  {
207  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::re_uc_m);
208  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
209  this->expect_false(entry.rw());
210  this->expect_false(entry.nx());
211  this->expect_true(entry.pat_index_large() == 7);
212  root_cr3.unmap(0x1000UL);
213  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
214  }
215 
216  // Pass Through
217  {
218  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::pt_uc);
219  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
220  this->expect_true(entry.rw());
221  this->expect_false(entry.nx());
222  this->expect_true(entry.pat_index_large() == 0);
223  root_cr3.unmap(0x1000UL);
224  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
225  }
226 
227  {
228  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::pt_wc);
229  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
230  this->expect_true(entry.rw());
231  this->expect_false(entry.nx());
232  this->expect_true(entry.pat_index_large() == 1);
233  root_cr3.unmap(0x1000UL);
234  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
235  }
236 
237  {
238  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::pt_wt);
239  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
240  this->expect_true(entry.rw());
241  this->expect_false(entry.nx());
242  this->expect_true(entry.pat_index_large() == 2);
243  root_cr3.unmap(0x1000UL);
244  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
245  }
246 
247  {
248  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::pt_wp);
249  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
250  this->expect_true(entry.rw());
251  this->expect_false(entry.nx());
252  this->expect_true(entry.pat_index_large() == 5);
253  root_cr3.unmap(0x1000UL);
254  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
255  }
256 
257  {
258  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::pt_wb);
259  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
260  this->expect_true(entry.rw());
261  this->expect_false(entry.nx());
262  this->expect_true(entry.pat_index_large() == 3);
263  root_cr3.unmap(0x1000UL);
264  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
265  }
266 
267  {
268  root_cr3.map_1g(0x1000UL, 0x1000UL, x64::memory_attr::pt_uc_m);
269  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
270  this->expect_true(entry.rw());
271  this->expect_false(entry.nx());
272  this->expect_true(entry.pat_index_large() == 7);
273  root_cr3.unmap(0x1000UL);
274  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
275  }
276 }
277 
278 void
279 memory_manager_ut::test_root_page_table_x64_map_2m()
280 {
281  MockRepository mocks;
282  setup_mm(mocks);
283  auto &&root_cr3 = root_page_table_x64{};
284 
285  // Read / Write
286  {
287  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::rw_uc);
288  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
289  this->expect_true(entry.rw());
290  this->expect_true(entry.nx());
291  this->expect_true(entry.pat_index_large() == 0);
292  root_cr3.unmap(0x1000UL);
293  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
294  }
295 
296  {
297  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::rw_wc);
298  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
299  this->expect_true(entry.rw());
300  this->expect_true(entry.nx());
301  this->expect_true(entry.pat_index_large() == 1);
302  root_cr3.unmap(0x1000UL);
303  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
304  }
305 
306  {
307  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::rw_wt);
308  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
309  this->expect_true(entry.rw());
310  this->expect_true(entry.nx());
311  this->expect_true(entry.pat_index_large() == 2);
312  root_cr3.unmap(0x1000UL);
313  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
314  }
315 
316  {
317  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::rw_wp);
318  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
319  this->expect_true(entry.rw());
320  this->expect_true(entry.nx());
321  this->expect_true(entry.pat_index_large() == 5);
322  root_cr3.unmap(0x1000UL);
323  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
324  }
325 
326  {
327  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::rw_wb);
328  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
329  this->expect_true(entry.rw());
330  this->expect_true(entry.nx());
331  this->expect_true(entry.pat_index_large() == 3);
332  root_cr3.unmap(0x1000UL);
333  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
334  }
335 
336  {
337  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::rw_uc_m);
338  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
339  this->expect_true(entry.rw());
340  this->expect_true(entry.nx());
341  this->expect_true(entry.pat_index_large() == 7);
342  root_cr3.unmap(0x1000UL);
343  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
344  }
345 
346  // Read / Execute
347  {
348  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::re_uc);
349  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
350  this->expect_false(entry.rw());
351  this->expect_false(entry.nx());
352  this->expect_true(entry.pat_index_large() == 0);
353  root_cr3.unmap(0x1000UL);
354  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
355  }
356 
357  {
358  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::re_wc);
359  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
360  this->expect_false(entry.rw());
361  this->expect_false(entry.nx());
362  this->expect_true(entry.pat_index_large() == 1);
363  root_cr3.unmap(0x1000UL);
364  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
365  }
366 
367  {
368  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::re_wt);
369  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
370  this->expect_false(entry.rw());
371  this->expect_false(entry.nx());
372  this->expect_true(entry.pat_index_large() == 2);
373  root_cr3.unmap(0x1000UL);
374  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
375  }
376 
377  {
378  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::re_wp);
379  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
380  this->expect_false(entry.rw());
381  this->expect_false(entry.nx());
382  this->expect_true(entry.pat_index_large() == 5);
383  root_cr3.unmap(0x1000UL);
384  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
385  }
386 
387  {
388  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::re_wb);
389  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
390  this->expect_false(entry.rw());
391  this->expect_false(entry.nx());
392  this->expect_true(entry.pat_index_large() == 3);
393  root_cr3.unmap(0x1000UL);
394  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
395  }
396 
397  {
398  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::re_uc_m);
399  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
400  this->expect_false(entry.rw());
401  this->expect_false(entry.nx());
402  this->expect_true(entry.pat_index_large() == 7);
403  root_cr3.unmap(0x1000UL);
404  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
405  }
406 
407  // Pass Through
408  {
409  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::pt_uc);
410  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
411  this->expect_true(entry.rw());
412  this->expect_false(entry.nx());
413  this->expect_true(entry.pat_index_large() == 0);
414  root_cr3.unmap(0x1000UL);
415  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
416  }
417 
418  {
419  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::pt_wc);
420  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
421  this->expect_true(entry.rw());
422  this->expect_false(entry.nx());
423  this->expect_true(entry.pat_index_large() == 1);
424  root_cr3.unmap(0x1000UL);
425  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
426  }
427 
428  {
429  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::pt_wt);
430  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
431  this->expect_true(entry.rw());
432  this->expect_false(entry.nx());
433  this->expect_true(entry.pat_index_large() == 2);
434  root_cr3.unmap(0x1000UL);
435  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
436  }
437 
438  {
439  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::pt_wp);
440  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
441  this->expect_true(entry.rw());
442  this->expect_false(entry.nx());
443  this->expect_true(entry.pat_index_large() == 5);
444  root_cr3.unmap(0x1000UL);
445  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
446  }
447 
448  {
449  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::pt_wb);
450  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
451  this->expect_true(entry.rw());
452  this->expect_false(entry.nx());
453  this->expect_true(entry.pat_index_large() == 3);
454  root_cr3.unmap(0x1000UL);
455  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
456  }
457 
458  {
459  root_cr3.map_2m(0x1000UL, 0x1000UL, x64::memory_attr::pt_uc_m);
460  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
461  this->expect_true(entry.rw());
462  this->expect_false(entry.nx());
463  this->expect_true(entry.pat_index_large() == 7);
464  root_cr3.unmap(0x1000UL);
465  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
466  }
467 }
468 
469 void
470 memory_manager_ut::test_root_page_table_x64_map_4k()
471 {
472  MockRepository mocks;
473  setup_mm(mocks);
474  auto &&root_cr3 = root_page_table_x64{};
475 
476  // Read / Write
477  {
478  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::rw_uc);
479  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
480  this->expect_true(entry.rw());
481  this->expect_true(entry.nx());
482  this->expect_true(entry.pat_index_4k() == 0);
483  root_cr3.unmap(0x1000UL);
484  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
485  }
486 
487  {
488  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::rw_wc);
489  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
490  this->expect_true(entry.rw());
491  this->expect_true(entry.nx());
492  this->expect_true(entry.pat_index_4k() == 1);
493  root_cr3.unmap(0x1000UL);
494  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
495  }
496 
497  {
498  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::rw_wt);
499  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
500  this->expect_true(entry.rw());
501  this->expect_true(entry.nx());
502  this->expect_true(entry.pat_index_4k() == 2);
503  root_cr3.unmap(0x1000UL);
504  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
505  }
506 
507  {
508  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::rw_wp);
509  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
510  this->expect_true(entry.rw());
511  this->expect_true(entry.nx());
512  this->expect_true(entry.pat_index_4k() == 5);
513  root_cr3.unmap(0x1000UL);
514  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
515  }
516 
517  {
518  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::rw_wb);
519  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
520  this->expect_true(entry.rw());
521  this->expect_true(entry.nx());
522  this->expect_true(entry.pat_index_4k() == 3);
523  root_cr3.unmap(0x1000UL);
524  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
525  }
526 
527  {
528  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::rw_uc_m);
529  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
530  this->expect_true(entry.rw());
531  this->expect_true(entry.nx());
532  this->expect_true(entry.pat_index_4k() == 7);
533  root_cr3.unmap(0x1000UL);
534  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
535  }
536 
537  // Read / Execute
538  {
539  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::re_uc);
540  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
541  this->expect_false(entry.rw());
542  this->expect_false(entry.nx());
543  this->expect_true(entry.pat_index_4k() == 0);
544  root_cr3.unmap(0x1000UL);
545  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
546  }
547 
548  {
549  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::re_wc);
550  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
551  this->expect_false(entry.rw());
552  this->expect_false(entry.nx());
553  this->expect_true(entry.pat_index_4k() == 1);
554  root_cr3.unmap(0x1000UL);
555  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
556  }
557 
558  {
559  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::re_wt);
560  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
561  this->expect_false(entry.rw());
562  this->expect_false(entry.nx());
563  this->expect_true(entry.pat_index_4k() == 2);
564  root_cr3.unmap(0x1000UL);
565  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
566  }
567 
568  {
569  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::re_wp);
570  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
571  this->expect_false(entry.rw());
572  this->expect_false(entry.nx());
573  this->expect_true(entry.pat_index_4k() == 5);
574  root_cr3.unmap(0x1000UL);
575  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
576  }
577 
578  {
579  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::re_wb);
580  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
581  this->expect_false(entry.rw());
582  this->expect_false(entry.nx());
583  this->expect_true(entry.pat_index_4k() == 3);
584  root_cr3.unmap(0x1000UL);
585  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
586  }
587 
588  {
589  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::re_uc_m);
590  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
591  this->expect_false(entry.rw());
592  this->expect_false(entry.nx());
593  this->expect_true(entry.pat_index_4k() == 7);
594  root_cr3.unmap(0x1000UL);
595  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
596  }
597 
598  // Pass Through
599  {
600  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::pt_uc);
601  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
602  this->expect_true(entry.rw());
603  this->expect_false(entry.nx());
604  this->expect_true(entry.pat_index_4k() == 0);
605  root_cr3.unmap(0x1000UL);
606  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
607  }
608 
609  {
610  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::pt_wc);
611  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
612  this->expect_true(entry.rw());
613  this->expect_false(entry.nx());
614  this->expect_true(entry.pat_index_4k() == 1);
615  root_cr3.unmap(0x1000UL);
616  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
617  }
618 
619  {
620  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::pt_wt);
621  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
622  this->expect_true(entry.rw());
623  this->expect_false(entry.nx());
624  this->expect_true(entry.pat_index_4k() == 2);
625  root_cr3.unmap(0x1000UL);
626  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
627  }
628 
629  {
630  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::pt_wp);
631  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
632  this->expect_true(entry.rw());
633  this->expect_false(entry.nx());
634  this->expect_true(entry.pat_index_4k() == 5);
635  root_cr3.unmap(0x1000UL);
636  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
637  }
638 
639  {
640  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::pt_wb);
641  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
642  this->expect_true(entry.rw());
643  this->expect_false(entry.nx());
644  this->expect_true(entry.pat_index_4k() == 3);
645  root_cr3.unmap(0x1000UL);
646  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
647  }
648 
649  {
650  root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::pt_uc_m);
651  auto &&entry = root_cr3.virt_to_pte(0x1000UL);
652  this->expect_true(entry.rw());
653  this->expect_false(entry.nx());
654  this->expect_true(entry.pat_index_4k() == 7);
655  root_cr3.unmap(0x1000UL);
656  this->expect_exception([&] { root_cr3.virt_to_pte(0x1000UL); }, ""_ut_ree);
657  }
658 }
659 
660 void
661 memory_manager_ut::test_root_page_table_x64_map_invalid()
662 {
663  MockRepository mocks;
664  setup_mm(mocks);
665  auto &&root_cr3 = root_page_table_x64{};
666 
667  this->expect_exception([&] { root_cr3.map_page(0x0, 0x0, 0x0, 0x0); }, ""_ut_lee);
668  this->expect_exception([&] { root_cr3.map_page(0x0, 0x0, 0x0, x64::page_table::pt::size_bytes); }, ""_ut_lee);
669 }
670 
671 void
672 memory_manager_ut::test_root_page_table_x64_map_unmap_twice_success()
673 {
674  MockRepository mocks;
675  setup_mm(mocks);
676  auto &&root_cr3 = root_page_table_x64{};
677 
678  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
679  {
680  this->expect_no_exception([&] { root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::pt_wb); });
681  this->expect_no_exception([&] { root_cr3.map_4k(0x1000UL, 0x1000UL, x64::memory_attr::pt_wb); });
682  this->expect_no_exception([&] { root_cr3.unmap(0x1000UL); });
683  this->expect_no_exception([&] { root_cr3.unmap(0x1000UL); });
684  });
685 }
686 
687 void
688 memory_manager_ut::test_root_page_table_x64_setup_identity_map_1g_invalid()
689 {
690  MockRepository mocks;
691  setup_mm(mocks);
692  auto &&root_cr3 = root_page_table_x64{};
693 
694  this->expect_exception([&] { root_cr3.setup_identity_map_1g(0x1, 0x40000000); }, ""_ut_ffe);
695  this->expect_exception([&] { root_cr3.setup_identity_map_1g(0x0, 0x40000001); }, ""_ut_ffe);
696  this->expect_exception([&] { root_cr3.unmap_identity_map_1g(0x1, 0x40000000); }, ""_ut_ffe);
697  this->expect_exception([&] { root_cr3.unmap_identity_map_1g(0x0, 0x40000001); }, ""_ut_ffe);
698 }
699 
700 void
701 memory_manager_ut::test_root_page_table_x64_setup_identity_map_1g_valid()
702 {
703  MockRepository mocks;
704  setup_mm(mocks);
705  auto &&root_cr3 = root_page_table_x64{};
706 
707  this->expect_no_exception([&] { root_cr3.setup_identity_map_1g(0x0, 0x40000000); });
708  this->expect_no_exception([&] { root_cr3.unmap_identity_map_1g(0x0, 0x40000000); });
709 }
710 
711 void
712 memory_manager_ut::test_root_page_table_x64_setup_identity_map_2m_invalid()
713 {
714  MockRepository mocks;
715  setup_mm(mocks);
716  auto &&root_cr3 = root_page_table_x64{};
717 
718  this->expect_exception([&] { root_cr3.setup_identity_map_2m(0x1, 0x200000); }, ""_ut_ffe);
719  this->expect_exception([&] { root_cr3.setup_identity_map_2m(0x0, 0x200001); }, ""_ut_ffe);
720  this->expect_exception([&] { root_cr3.unmap_identity_map_2m(0x1, 0x200000); }, ""_ut_ffe);
721  this->expect_exception([&] { root_cr3.unmap_identity_map_2m(0x0, 0x200001); }, ""_ut_ffe);
722 }
723 
724 void
725 memory_manager_ut::test_root_page_table_x64_setup_identity_map_2m_valid()
726 {
727  MockRepository mocks;
728  setup_mm(mocks);
729  auto &&root_cr3 = root_page_table_x64{};
730 
731  this->expect_no_exception([&] { root_cr3.setup_identity_map_2m(0x0, 0x200000); });
732  this->expect_no_exception([&] { root_cr3.unmap_identity_map_2m(0x0, 0x200000); });
733 }
734 
735 void
736 memory_manager_ut::test_root_page_table_x64_setup_identity_map_4k_invalid()
737 {
738  MockRepository mocks;
739  setup_mm(mocks);
740  auto &&root_cr3 = root_page_table_x64{};
741 
742  this->expect_exception([&] { root_cr3.setup_identity_map_4k(0x1, 0x1000); }, ""_ut_ffe);
743  this->expect_exception([&] { root_cr3.setup_identity_map_4k(0x0, 0x1001); }, ""_ut_ffe);
744  this->expect_exception([&] { root_cr3.unmap_identity_map_4k(0x1, 0x1000); }, ""_ut_ffe);
745  this->expect_exception([&] { root_cr3.unmap_identity_map_4k(0x0, 0x1001); }, ""_ut_ffe);
746 }
747 
748 void
749 memory_manager_ut::test_root_page_table_x64_setup_identity_map_4k_valid()
750 {
751  MockRepository mocks;
752  setup_mm(mocks);
753  auto &&root_cr3 = root_page_table_x64{};
754 
755  this->expect_no_exception([&] { root_cr3.setup_identity_map_4k(0x0, 0x1000); });
756  this->expect_no_exception([&] { root_cr3.unmap_identity_map_4k(0x0, 0x1000); });
757 }
758 
759 void
760 memory_manager_ut::test_root_page_table_x64_pt_to_mdl()
761 {
762  MockRepository mocks;
763  setup_mm(mocks);
764  auto &&root_cr3 = root_page_table_x64{};
765 
766  this->expect_no_exception([&] { root_cr3.pt_to_mdl(); });
767 }
#define expect_exception(f, e)
Definition: unittest.h:162
constexpr const auto pt_wp
Definition: mem_attr_x64.h:60
virtual void add_md(integer_pointer virt, integer_pointer phys, attr_type attr)
virtual void map_2m(integer_pointer virt, integer_pointer phys, attr_type attr)
#define RUN_UNITTEST_WITH_MOCKS(a, b)
Definition: unittest.h:229
constexpr const auto re_wc
Definition: mem_attr_x64.h:51
virtual integer_pointer virtint_to_physint(integer_pointer virt) const
#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
#define expect_no_exception(f)
Definition: unittest.h:198
constexpr const auto re_uc_m
Definition: mem_attr_x64.h:55
bool g_terminate_called
constexpr const auto rw_uc_m
Definition: mem_attr_x64.h:48
constexpr const auto pt_wb
Definition: mem_attr_x64.h:61
#define MEMORY_TYPE_R
Definition: memory.h:39
virtual integer_pointer virtptr_to_physint(pointer virt) const
constexpr const auto re_wt
Definition: mem_attr_x64.h:52
constexpr const auto size_bytes
virtual void map_4k(integer_pointer virt, integer_pointer phys, attr_type attr)
constexpr const auto rw_wb
Definition: mem_attr_x64.h:47
constexpr const auto rw_uc
Definition: mem_attr_x64.h:43
constexpr const auto pt_wt
Definition: mem_attr_x64.h:59
static memory_manager_x64 * instance() noexcept
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 const auto rw_wc
Definition: mem_attr_x64.h:44
constexpr const auto pt_uc_m
Definition: mem_attr_x64.h:62
virtual memory_descriptor_list descriptors() const
#define expect_false(a)
virtual void remove_md(integer_pointer virt) noexcept
constexpr const auto rw_wt
Definition: mem_attr_x64.h:45
constexpr const auto rw_wp
Definition: mem_attr_x64.h:46
constexpr const auto re_wb
Definition: mem_attr_x64.h:54
#define expect_true(a)
root_page_table_x64 * root_pt() noexcept