test_vcpu_intel_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 <stdlib.h>
24 #include <vcpu/vcpu_intel_x64.h>
25 #include <debug_ring/debug_ring.h>
28 
29 #include <intrinsics/cpuid_x64.h>
30 
31 using namespace x64;
32 
33 extern "C" uint64_t
35 { (void) addr; return 0; }
36 
37 extern "C" uint64_t
39 { return 0; }
40 
41 extern "C" uint64_t
43 { return 0; }
44 
45 extern "C" uint64_t
47 { return 0; }
48 
49 extern "C" uint64_t
51 { return 0; }
52 
53 extern "C" uint64_t
55 { return 0; }
56 
57 extern "C" void
59 { (void) gdt_reg; }
60 
61 extern "C" void
63 { (void) idt_reg; }
64 
65 extern "C" uint16_t
67 { return 0; }
68 
69 extern "C" uint16_t
71 { return 0; }
72 
73 extern "C" uint16_t
75 { return 0; }
76 
77 extern "C" uint16_t
79 { return 0; }
80 
81 extern "C" uint16_t
83 { return 0; }
84 
85 extern "C" uint16_t
87 { return 0; }
88 
89 extern "C" uint16_t
91 { return 0; }
92 
93 extern "C" uint16_t
95 { return 0; }
96 
97 extern "C" uint32_t
98 __cpuid_ecx(uint32_t val) noexcept
99 { (void) val; return 0x04000000U; }
100 
101 extern "C" uint32_t
102 __cpuid_eax(uint32_t val) noexcept
103 { (void) val; return 0x2U; }
104 
105 extern "C" void
106 __cpuid(void *eax, void *ebx, void *ecx, void *edx) noexcept
107 {
108  *static_cast<cpuid::value_type *>(eax) = 0;
109  *static_cast<cpuid::value_type *>(ebx) = 0;
110  *static_cast<cpuid::value_type *>(ecx) = 0;
111  *static_cast<cpuid::value_type *>(edx) = 0;
112 }
113 
114 static auto
115 setup_mm(MockRepository &mocks)
116 {
117  auto mm = mocks.Mock<memory_manager_x64>();
118  mocks.OnCallFunc(memory_manager_x64::instance).Return(mm);
119  mocks.OnCall(mm, memory_manager_x64::virtptr_to_physint).Return(0x000000ABCDEF0000);
120 
121  return mm;
122 }
123 
124 static auto
125 setup_pt(MockRepository &mocks)
126 {
127  auto pt = mocks.Mock<root_page_table_x64>();
128  mocks.OnCallFunc(root_pt).Return(pt);
129  mocks.OnCall(pt, root_page_table_x64::cr3).Return(0x000000ABCDEF0000);
130 
131  return pt;
132 }
133 
134 void
135 vcpu_ut::test_vcpu_intel_x64_invalid_id()
136 {
137  this->expect_exception([&] { std::make_unique<vcpu_intel_x64>(vcpuid::reserved); }, ""_ut_iae);
138 }
139 
140 void
141 vcpu_ut::test_vcpu_intel_x64_valid()
142 {
143  MockRepository mocks;
144  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
145  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
146  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
147  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
148  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
149  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
150 
151  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
152  {
153  this->expect_no_exception([&] {
154  std::make_unique<vcpu_intel_x64>(
155  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
156  });
157  });
158 }
159 
160 void
161 vcpu_ut::test_vcpu_intel_x64_init_null_params()
162 {
163  MockRepository mocks;
164  setup_mm(mocks);
165  setup_pt(mocks);
166 
167  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
168  {
169  auto vc = std::make_unique<vcpu_intel_x64>(0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
170 
171  this->expect_no_exception([&]{ vc->init(); });
172  });
173 }
174 
175 void
176 vcpu_ut::test_vcpu_intel_x64_init_valid_params()
177 {
178  MockRepository mocks;
179  setup_mm(mocks);
180  setup_pt(mocks);
181 
182  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
183  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
184  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
185  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
186  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
187  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
188 
189  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
190 
191  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
192  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
193 
194  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
195  {
196  auto vc = std::make_unique<vcpu_intel_x64>(
197  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
198 
199  this->expect_no_exception([&]{ vc->init(); });
200  });
201 }
202 
203 void
204 vcpu_ut::test_vcpu_intel_x64_init_valid()
205 {
206  MockRepository mocks;
207  setup_mm(mocks);
208  setup_pt(mocks);
209 
210  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
211  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
212  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
213  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
214  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
215  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
216 
217  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
218 
219  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
220  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
221 
222  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
223  {
224  auto vc = std::make_unique<vcpu_intel_x64>(
225  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
226 
227  this->expect_no_exception([&]{ vc->init(); });
228  });
229 }
230 
231 void
232 vcpu_ut::test_vcpu_intel_x64_init_vmcs_throws()
233 {
234  MockRepository mocks;
235  setup_mm(mocks);
236  setup_pt(mocks);
237 
238  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
239  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
240  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
241  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
242  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
243  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
244 
245  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save).Throw(std::logic_error("error"));
246 
247  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
248  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
249 
250  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
251  {
252  auto vc = std::make_unique<vcpu_intel_x64>(
253  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
254 
255  this->expect_exception([&] { vc->init(); }, ""_ut_lee);
256  });
257 }
258 
259 void
260 vcpu_ut::test_vcpu_intel_x64_fini_null_params()
261 {
262  MockRepository mocks;
263  setup_mm(mocks);
264  setup_pt(mocks);
265 
266  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
267  {
268  auto vc = std::make_unique<vcpu_intel_x64>(0, nullptr, nullptr, nullptr, nullptr, nullptr);
269 
270  vc->init();
271  this->expect_no_exception([&]{ vc->fini(); });
272  });
273 }
274 
275 void
276 vcpu_ut::test_vcpu_intel_x64_fini_valid_params()
277 {
278  MockRepository mocks;
279  setup_mm(mocks);
280  setup_pt(mocks);
281 
282  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
283  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
284  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
285  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
286  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
287  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
288 
289  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
290 
291  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
292  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
293 
294  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
295  {
296  auto vc = std::make_unique<vcpu_intel_x64>(
297  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
298 
299  vc->init();
300  this->expect_no_exception([&]{ vc->fini(); });
301  });
302 }
303 
304 void
305 vcpu_ut::test_vcpu_intel_x64_fini_valid()
306 {
307  MockRepository mocks;
308  setup_mm(mocks);
309  setup_pt(mocks);
310 
311  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
312  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
313  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
314  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
315  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
316  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
317 
318  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
319 
320  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
321  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
322 
323  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
324  {
325  auto vc = std::make_unique<vcpu_intel_x64>(
326  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
327 
328  vc->init();
329  this->expect_no_exception([&]{ vc->fini(); });
330  });
331 }
332 
333 void
334 vcpu_ut::test_vcpu_intel_x64_fini_no_init()
335 {
336  MockRepository mocks;
337  setup_mm(mocks);
338  setup_pt(mocks);
339 
340  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
341  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
342  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
343  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
344  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
345  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
346 
347  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
348  {
349  auto vc = std::make_unique<vcpu_intel_x64>(
350  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
351 
352  this->expect_no_exception([&]{ vc->fini(); });
353  });
354 }
355 
356 void
357 vcpu_ut::test_vcpu_intel_x64_run_launch()
358 {
359  MockRepository mocks;
360  setup_mm(mocks);
361  setup_pt(mocks);
362 
363  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
364  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
365  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
366  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
367  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
368  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
369 
370  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
371  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
372  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
373  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
374 
375  mocks.OnCall(on.get(), vmxon_intel_x64::start);
376  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
377 
378  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
379  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
380 
381  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
382  {
383  auto vc = std::make_unique<vcpu_intel_x64>(
384  0x0001000000000000, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
385 
386  vc->init();
387  this->expect_no_exception([&]{ vc->run(); });
388  });
389 }
390 
391 void
392 vcpu_ut::test_vcpu_intel_x64_run_launch_is_host_vcpu()
393 {
394  MockRepository mocks;
395  setup_mm(mocks);
396  setup_pt(mocks);
397 
398  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
399  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
400  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
401  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
402  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
403  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
404 
405  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
406  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
407  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
408  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
409 
410  mocks.OnCall(on.get(), vmxon_intel_x64::start);
411  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
412 
413  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
414  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
415 
416  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
417  {
418  auto vc = std::make_unique<vcpu_intel_x64>(
419  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
420 
421  vc->init();
422  this->expect_no_exception([&]{ vc->run(); });
423  });
424 }
425 
426 void
427 vcpu_ut::test_vcpu_intel_x64_run_resume()
428 {
429  MockRepository mocks;
430  setup_mm(mocks);
431  setup_pt(mocks);
432 
433  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
434  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
435  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
436  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
437  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
438  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
439 
440  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
441  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
442  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
443  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
444 
445  mocks.OnCall(on.get(), vmxon_intel_x64::start);
446  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
447 
448  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
449  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
450 
451  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
452  {
453  auto vc = std::make_unique<vcpu_intel_x64>(
454  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
455 
456  vc->init();
457  vc->run();
458  this->expect_no_exception([&]{ vc->run(); });
459  });
460 }
461 
462 void
463 vcpu_ut::test_vcpu_intel_x64_run_no_init()
464 {
465  MockRepository mocks;
466  setup_mm(mocks);
467  setup_pt(mocks);
468 
469  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
470  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
471  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
472  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
473  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
474  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
475 
476  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
477  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
478  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
479  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
480 
481  mocks.OnCall(on.get(), vmxon_intel_x64::start);
482  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
483 
484  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
485  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
486 
487  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
488  {
489  auto vc = std::make_unique<vcpu_intel_x64>(
490  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
491 
492  this->expect_exception([&] { vc->run(); }, ""_ut_ffe);
493  });
494 }
495 
496 void
497 vcpu_ut::test_vcpu_intel_x64_run_vmxon_throws()
498 {
499  MockRepository mocks;
500  setup_mm(mocks);
501  setup_pt(mocks);
502 
503  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
504  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
505  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
506  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
507  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
508  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
509 
510  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
511  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
512  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
513  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
514 
515  mocks.OnCall(on.get(), vmxon_intel_x64::start).Throw(std::runtime_error("error"));
516  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
517 
518  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
519  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
520 
521  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
522  {
523  auto vc = std::make_unique<vcpu_intel_x64>(
524  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
525 
526  vc->init();
527  this->expect_exception([&] { vc->run(); }, ""_ut_ree);
528  });
529 }
530 
531 void
532 vcpu_ut::test_vcpu_intel_x64_run_vmcs_throws()
533 {
534  MockRepository mocks;
535  setup_mm(mocks);
536  setup_pt(mocks);
537 
538  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
539  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
540  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
541  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
542  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
543  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
544 
545  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
546  mocks.OnCall(cs.get(), vmcs_intel_x64::launch).Throw(std::runtime_error("error"));
547  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
548  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
549 
550  mocks.OnCall(on.get(), vmxon_intel_x64::start);
551  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
552 
553  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
554  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
555 
556  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
557  {
558  auto vc = std::make_unique<vcpu_intel_x64>(
559  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
560 
561  vc->init();
562  this->expect_exception([&] { vc->run(); }, ""_ut_ree);
563  });
564 }
565 
566 void
567 vcpu_ut::test_vcpu_intel_x64_hlt_no_init()
568 {
569  MockRepository mocks;
570  setup_mm(mocks);
571  setup_pt(mocks);
572 
573  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
574  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
575  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
576  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
577  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
578  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
579 
580  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
581  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
582  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
583  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
584 
585  mocks.OnCall(on.get(), vmxon_intel_x64::start);
586  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
587 
588  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
589  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
590 
591  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
592  {
593  auto vc = std::make_unique<vcpu_intel_x64>(
594  0x0001000000000000, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
595 
596  this->expect_no_exception([&]{ vc->hlt(); });
597  });
598 }
599 
600 void
601 vcpu_ut::test_vcpu_intel_x64_hlt_no_run()
602 {
603  MockRepository mocks;
604  setup_mm(mocks);
605  setup_pt(mocks);
606 
607  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
608  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
609  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
610  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
611  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
612  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
613 
614  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
615  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
616  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
617  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
618 
619  mocks.OnCall(on.get(), vmxon_intel_x64::start);
620  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
621 
622  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
623  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
624 
625  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
626  {
627  auto vc = std::make_unique<vcpu_intel_x64>(
628  0x0001000000000000, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
629  vc->init();
630  this->expect_no_exception([&]{ vc->hlt(); });
631  });
632 }
633 
634 void
635 vcpu_ut::test_vcpu_intel_x64_hlt_valid()
636 {
637  MockRepository mocks;
638  setup_mm(mocks);
639  setup_pt(mocks);
640 
641  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
642  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
643  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
644  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
645  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
646  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
647 
648  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
649  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
650  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
651  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
652 
653  mocks.OnCall(on.get(), vmxon_intel_x64::start);
654  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
655 
656  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
657  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
658 
659  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
660  {
661  auto vc = std::make_unique<vcpu_intel_x64>(
662  0x0001000000000000, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
663 
664  vc->init();
665  vc->run();
666  this->expect_no_exception([&]{ vc->hlt(); });
667  });
668 }
669 
670 void
671 vcpu_ut::test_vcpu_intel_x64_hlt_valid_is_host_vcpu()
672 {
673  MockRepository mocks;
674  setup_mm(mocks);
675  setup_pt(mocks);
676 
677  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
678  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
679  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
680  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
681  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
682  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
683 
684  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
685  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
686  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
687  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
688 
689  mocks.OnCall(on.get(), vmxon_intel_x64::start);
690  mocks.OnCall(on.get(), vmxon_intel_x64::stop);
691 
692  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
693  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
694 
695  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
696  {
697  auto vc = std::make_unique<vcpu_intel_x64>(
698  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
699 
700  vc->init();
701  vc->run();
702  this->expect_no_exception([&]{ vc->hlt(); });
703  });
704 }
705 
706 void
707 vcpu_ut::test_vcpu_intel_x64_hlt_vmxon_throws()
708 {
709  MockRepository mocks;
710  setup_mm(mocks);
711  setup_pt(mocks);
712 
713  auto &&dr = bfn::mock_unique<debug_ring>(mocks);
714  auto &&on = bfn::mock_unique<vmxon_intel_x64>(mocks);
715  auto &&cs = bfn::mock_unique<vmcs_intel_x64>(mocks);
716  auto &&eh = bfn::mock_unique<exit_handler_intel_x64>(mocks);
717  auto &&vs = bfn::mock_unique<vmcs_intel_x64_vmm_state>(mocks);
718  auto &&gs = bfn::mock_unique<vmcs_intel_x64_host_vm_state>(mocks);
719 
720  mocks.OnCall(cs.get(), vmcs_intel_x64::set_state_save);
721  mocks.OnCall(cs.get(), vmcs_intel_x64::launch);
722  mocks.OnCall(cs.get(), vmcs_intel_x64::load);
723  mocks.OnCall(cs.get(), vmcs_intel_x64::resume);
724 
725  mocks.OnCall(on.get(), vmxon_intel_x64::start);
726  mocks.OnCall(on.get(), vmxon_intel_x64::stop).Throw(std::runtime_error("error"));
727 
728  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_vmcs);
729  mocks.OnCall(eh.get(), exit_handler_intel_x64::set_state_save);
730 
731  RUN_UNITTEST_WITH_MOCKS(mocks, [&]
732  {
733  auto vc = std::make_unique<vcpu_intel_x64>(
734  0, std::move(dr), std::move(on), std::move(cs), std::move(eh), std::move(vs), std::move(gs));
735 
736  vc->init();
737  vc->run();
738 
739  this->expect_exception([&] { vc->hlt(); }, ""_ut_ree);
740  });
741 }
virtual void set_vmcs(gsl::not_null< vmcs_intel_x64 *> vmcs)
virtual void launch(gsl::not_null< vmcs_intel_x64_state *> host_state, gsl::not_null< vmcs_intel_x64_state *> guest_state)
#define expect_exception(f, e)
Definition: unittest.h:162
uint64_t __read_cr0(void) noexcept
void __read_idt(idt_reg_x64_t *idt_reg) noexcept
void __read_gdt(gdt_reg_x64_t *gdt_reg) noexcept
#define RUN_UNITTEST_WITH_MOCKS(a, b)
Definition: unittest.h:229
uint16_t __read_ds(void) noexcept
#define expect_no_exception(f)
Definition: unittest.h:198
uint16_t __read_ss(void) noexcept
uint64_t __read_cr3(void) noexcept
virtual void resume()
void __cpuid(void *eax, void *ebx, void *ecx, void *edx) noexcept
virtual integer_pointer virtptr_to_physint(pointer virt) const
constexpr const auto pt
Definition: mem_attr_x64.h:41
uint32_t value_type
Definition: cpuid_x64.h:41
void uint64_t uint64_t uint64_t *rdx noexcept
uint16_t __read_tr(void) noexcept
constexpr const auto addr
Definition: cpuid_x64.h:80
virtual void set_state_save(gsl::not_null< state_save_intel_x64 *> state_save)
uint64_t __read_cr4(void) noexcept
uint32_t __cpuid_ecx(uint32_t val) noexcept
virtual cr3_type cr3()
uint64_t __read_msr(uint32_t addr) noexcept
static memory_manager_x64 * instance() noexcept
virtual void start()
uint16_t __read_es(void) noexcept
virtual void stop()
uint64_t __read_rflags(void) noexcept
virtual void load()
constexpr const auto reserved
Definition: vcpuid.h:33
uint16_t __read_fs(void) noexcept
uint32_t __cpuid_eax(uint32_t val) noexcept
void on(gsl::not_null< void *> ptr)
Definition: vmx_intel_x64.h:49
uint16_t __read_ldtr(void) noexcept
debug_ring * dr
uint16_t __read_gs(void) noexcept
uint16_t __read_cs(void) noexcept
Definition: cache_x64.h:31
uint64_t __read_dr7(void) noexcept
root_page_table_x64 * root_pt() noexcept