test_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 <gsl/gsl>
23 
24 #include <test.h>
27 
29 constexpr page_table_x64::integer_pointer virt = 0x0000100000000000UL;
30 
31 static auto
32 setup_mm(MockRepository &mocks)
33 {
34  auto mm = mocks.Mock<memory_manager_x64>();
35  mocks.OnCallFunc(memory_manager_x64::instance).Return(mm);
36  mocks.OnCall(mm, memory_manager_x64::virtptr_to_physint).Return(0x0000000ABCDEF0000);
37  mocks.OnCall(mm, memory_manager_x64::virtint_to_physint).Return(0x0000000ABCDEF0000);
38 
39  return mm;
40 }
41 
42 void
43 memory_manager_ut::test_page_table_x64_add_remove_page_success_without_setting()
44 {
45  MockRepository mocks;
46  setup_mm(mocks);
47 
48  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
49  {
50  auto &&scr3 = 0x0UL;
51  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
52 
53  pml4->add_page_4k(virt);
54  this->expect_true(pml4->global_size() == 3);
55  this->expect_true(pml4->global_capacity() == 512 * 3);
56 
57  pml4->add_page_4k(virt + 0x1000);
58  this->expect_true(pml4->global_size() == 3);
59  this->expect_true(pml4->global_capacity() == 512 * 3);
60 
61  pml4->add_page_4k(virt + 0x10000);
62  this->expect_true(pml4->global_size() == 3);
63  this->expect_true(pml4->global_capacity() == 512 * 3);
64 
65  pml4->remove_page(virt);
66  this->expect_true(pml4->global_size() == 0);
67  this->expect_true(pml4->global_capacity() == 512 * 1);
68 
69  pml4->remove_page(virt + 0x1000);
70  this->expect_true(pml4->global_size() == 0);
71  this->expect_true(pml4->global_capacity() == 512 * 1);
72 
73  pml4->remove_page(virt + 0x10000);
74  this->expect_true(pml4->global_size() == 0);
75  this->expect_true(pml4->global_capacity() == 512 * 1);
76  });
77 }
78 
79 void
80 memory_manager_ut::test_page_table_x64_add_remove_page_1g_success()
81 {
82  MockRepository mocks;
83  setup_mm(mocks);
84 
85  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
86  {
87  auto &&scr3 = 0x0UL;
88  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
89 
90  auto &&entry1 = pml4->add_page_1g(virt);
91  entry1.set_present(true);
92  this->expect_true(pml4->global_size() == 2);
93  this->expect_true(pml4->global_capacity() == 512 * 1);
94 
95  auto &&entry2 = pml4->add_page_1g(virt + 0x100);
96  entry2.set_present(true);
97  this->expect_true(pml4->global_size() == 2);
98  this->expect_true(pml4->global_capacity() == 512 * 1);
99 
100  auto &&entry3 = pml4->add_page_1g(virt + 0x40000000);
101  entry3.set_present(true);
102  this->expect_true(pml4->global_size() == 3);
103  this->expect_true(pml4->global_capacity() == 512 * 1);
104 
105  auto &&entry4 = pml4->add_page_1g(virt + 0x400000000);
106  entry4.set_present(true);
107  this->expect_true(pml4->global_size() == 4);
108  this->expect_true(pml4->global_capacity() == 512 * 1);
109 
110  pml4->remove_page(virt);
111  this->expect_true(pml4->global_size() == 3);
112  this->expect_true(pml4->global_capacity() == 512 * 1);
113 
114  pml4->remove_page(virt + 0x40000000);
115  this->expect_true(pml4->global_size() == 2);
116  this->expect_true(pml4->global_capacity() == 512 * 1);
117 
118  pml4->remove_page(virt + 0x400000000);
119  this->expect_true(pml4->global_size() == 0);
120  this->expect_true(pml4->global_capacity() == 512 * 1);
121  });
122 }
123 
124 void
125 memory_manager_ut::test_page_table_x64_add_remove_page_2m_success()
126 {
127  MockRepository mocks;
128  setup_mm(mocks);
129 
130  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
131  {
132  auto &&scr3 = 0x0UL;
133  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
134 
135  auto &&entry1 = pml4->add_page_2m(virt);
136  entry1.set_present(true);
137  this->expect_true(pml4->global_size() == 3);
138  this->expect_true(pml4->global_capacity() == 512 * 2);
139 
140  auto &&entry2 = pml4->add_page_2m(virt + 0x100);
141  entry2.set_present(true);
142  this->expect_true(pml4->global_size() == 3);
143  this->expect_true(pml4->global_capacity() == 512 * 2);
144 
145  auto &&entry3 = pml4->add_page_2m(virt + 0x200000);
146  entry3.set_present(true);
147  this->expect_true(pml4->global_size() == 4);
148  this->expect_true(pml4->global_capacity() == 512 * 2);
149 
150  auto &&entry4 = pml4->add_page_2m(virt + 0x2000000);
151  entry4.set_present(true);
152  this->expect_true(pml4->global_size() == 5);
153  this->expect_true(pml4->global_capacity() == 512 * 2);
154 
155  pml4->remove_page(virt);
156  this->expect_true(pml4->global_size() == 4);
157  this->expect_true(pml4->global_capacity() == 512 * 2);
158 
159  pml4->remove_page(virt + 0x200000);
160  this->expect_true(pml4->global_size() == 3);
161  this->expect_true(pml4->global_capacity() == 512 * 2);
162 
163  pml4->remove_page(virt + 0x2000000);
164  this->expect_true(pml4->global_size() == 0);
165  this->expect_true(pml4->global_capacity() == 512 * 1);
166  });
167 }
168 
169 void
170 memory_manager_ut::test_page_table_x64_add_remove_page_4k_success()
171 {
172  MockRepository mocks;
173  setup_mm(mocks);
174 
175  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
176  {
177  auto &&scr3 = 0x0UL;
178  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
179 
180  auto &&entry1 = pml4->add_page_4k(virt);
181  entry1.set_present(true);
182  this->expect_true(pml4->global_size() == 4);
183  this->expect_true(pml4->global_capacity() == 512 * 3);
184 
185  auto &&entry2 = pml4->add_page_4k(virt + 0x100);
186  entry2.set_present(true);
187  this->expect_true(pml4->global_size() == 4);
188  this->expect_true(pml4->global_capacity() == 512 * 3);
189 
190  auto &&entry3 = pml4->add_page_4k(virt + 0x1000);
191  entry3.set_present(true);
192  this->expect_true(pml4->global_size() == 5);
193  this->expect_true(pml4->global_capacity() == 512 * 3);
194 
195  auto &&entry4 = pml4->add_page_4k(virt + 0x10000);
196  entry4.set_present(true);
197  this->expect_true(pml4->global_size() == 6);
198  this->expect_true(pml4->global_capacity() == 512 * 3);
199 
200  pml4->remove_page(virt);
201  this->expect_true(pml4->global_size() == 5);
202  this->expect_true(pml4->global_capacity() == 512 * 3);
203 
204  pml4->remove_page(virt + 0x1000);
205  this->expect_true(pml4->global_size() == 4);
206  this->expect_true(pml4->global_capacity() == 512 * 3);
207 
208  pml4->remove_page(virt + 0x10000);
209  this->expect_true(pml4->global_size() == 0);
210  this->expect_true(pml4->global_capacity() == 512 * 1);
211  });
212 }
213 
214 void
215 memory_manager_ut::test_page_table_x64_add_remove_page_swap_success()
216 {
217  MockRepository mocks;
218  setup_mm(mocks);
219 
220  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
221  {
222  auto &&scr3 = 0x0UL;
223  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
224 
225  auto &&entry1 = pml4->add_page_4k(virt);
226  entry1.set_present(true);
227  this->expect_true(pml4->global_size() == 4);
228  this->expect_true(pml4->global_capacity() == 512 * 3);
229 
230  pml4->remove_page(virt);
231  this->expect_true(pml4->global_size() == 0);
232  this->expect_true(pml4->global_capacity() == 512 * 1);
233 
234  auto &&entry2 = pml4->add_page_2m(virt);
235  entry2.set_present(true);
236  this->expect_true(pml4->global_size() == 3);
237  this->expect_true(pml4->global_capacity() == 512 * 2);
238 
239  pml4->remove_page(virt);
240  this->expect_true(pml4->global_size() == 0);
241  this->expect_true(pml4->global_capacity() == 512 * 1);
242 
243  auto &&entry3 = pml4->add_page_4k(virt);
244  entry3.set_present(true);
245  this->expect_true(pml4->global_size() == 4);
246  this->expect_true(pml4->global_capacity() == 512 * 3);
247 
248  auto &&entry4 = pml4->add_page_2m(virt);
249  entry4.set_present(true);
250  this->expect_true(pml4->global_size() == 3);
251  this->expect_true(pml4->global_capacity() == 512 * 2);
252 
253  auto &&entry5 = pml4->add_page_4k(virt);
254  entry5.set_present(true);
255  this->expect_true(pml4->global_size() == 4);
256  this->expect_true(pml4->global_capacity() == 512 * 3);
257 
258  pml4->remove_page(virt);
259  this->expect_true(pml4->global_size() == 0);
260  this->expect_true(pml4->global_capacity() == 512 * 1);
261  });
262 }
263 
264 void
265 memory_manager_ut::test_page_table_x64_add_page_twice_success()
266 {
267  MockRepository mocks;
268  setup_mm(mocks);
269 
270  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
271  {
272  auto &&scr3 = 0x0UL;
273  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
274 
275  pml4->add_page_4k(virt);
276  this->expect_no_exception([&]{ pml4->add_page_4k(virt); });
277  });
278 }
279 
280 void
281 memory_manager_ut::test_page_table_x64_remove_page_twice_success()
282 {
283  MockRepository mocks;
284  setup_mm(mocks);
285 
286  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
287  {
288  auto &&scr3 = 0x0UL;
289  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
290 
291  pml4->add_page_4k(virt);
292  pml4->add_page_4k(virt + 0x1000);
293 
294  pml4->remove_page(virt);
295  this->expect_no_exception([&]{ pml4->remove_page(virt); });
296  pml4->remove_page(virt + 0x1000);
297 
298  this->expect_true(pml4->global_size() == 0);
299  });
300 }
301 
302 void
303 memory_manager_ut::test_page_table_x64_remove_page_unknown_success()
304 {
305  MockRepository mocks;
306  setup_mm(mocks);
307 
308  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
309  {
310  auto &&scr3 = 0x0UL;
311  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
312  this->expect_no_exception([&]{ pml4->remove_page(virt); });
313  });
314 }
315 
316 void
317 memory_manager_ut::test_page_table_x64_virt_to_pte_invalid()
318 {
319  MockRepository mocks;
320  setup_mm(mocks);
321 
322  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
323  {
324  auto &&scr3 = 0x0UL;
325  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
326 
327  pml4->add_page_4k(virt);
328 
329  this->expect_exception([&]{ pml4->virt_to_pte(virt + 0x40000000); }, ""_ut_ree);
330 
331  pml4->remove_page(virt);
332  this->expect_true(pml4->global_size() == 0);
333  });
334 }
335 
336 void
337 memory_manager_ut::test_page_table_x64_virt_to_pte_success()
338 {
339  MockRepository mocks;
340  setup_mm(mocks);
341 
342  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
343  {
344  auto &&scr3 = 0x0UL;
345  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
346 
347  pml4->add_page_4k(virt);
348  this->expect_no_exception([&]{ pml4->virt_to_pte(virt); });
349 
350  pml4->remove_page(virt);
351  this->expect_true(pml4->global_size() == 0);
352  });
353 }
354 
355 void
356 memory_manager_ut::test_page_table_x64_pt_to_mdl_success()
357 {
358  MockRepository mocks;
359  setup_mm(mocks);
360 
361  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
362  {
363  auto &&scr3 = 0x0UL;
364  auto &&pml4 = std::make_unique<page_table_x64>(&scr3);
365 
366  this->expect_true(pml4->pt_to_mdl().size() == 1);
367  pml4->add_page_1g(0x1000);
368  this->expect_true(pml4->pt_to_mdl().size() == 2);
369  pml4->add_page_2m(0x1000);
370  this->expect_true(pml4->pt_to_mdl().size() == 3);
371  pml4->add_page_4k(0x1000);
372  this->expect_true(pml4->pt_to_mdl().size() == 4);
373 
374  pml4->remove_page(0x1000);
375  this->expect_true(pml4->global_size() == 0);
376  });
377 }
#define expect_exception(f, e)
Definition: unittest.h:162
#define RUN_UNITTEST_WITH_MOCKS(a, b)
Definition: unittest.h:229
virtual integer_pointer virtint_to_physint(integer_pointer virt) const
#define expect_no_exception(f)
Definition: unittest.h:198
virtual integer_pointer virtptr_to_physint(pointer virt) const
static memory_manager_x64 * instance() noexcept
constexpr page_table_x64::integer_pointer virt
bool virt_to_phys_return_nullptr
uintptr_t integer_pointer
#define expect_true(a)