test_vmcs_intel_x64_host_vm_state.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 // Author: Connor Davis <davisc@ainfosec.com>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 
23 #include <test.h>
25 
26 #include <intrinsics/srs_x64.h>
27 #include <intrinsics/gdt_x64.h>
28 #include <intrinsics/idt_x64.h>
29 #include <intrinsics/debug_x64.h>
31 #include <intrinsics/msrs_x64.h>
33 
34 using namespace x64;
35 
36 uint16_t test_es;
37 uint16_t test_cs;
38 uint16_t test_ss;
39 uint16_t test_ds;
40 uint16_t test_fs;
41 uint16_t test_gs;
42 uint16_t test_ldtr;
43 uint16_t test_tr;
44 
45 uint16_t test_es_index;
46 uint16_t test_cs_index;
47 uint16_t test_ss_index;
48 uint16_t test_ds_index;
49 uint16_t test_fs_index;
50 uint16_t test_gs_index;
51 uint16_t test_ldtr_index;
52 uint16_t test_tr_index;
53 uint16_t test_gdt_index;
54 
55 uint64_t test_cr0;
56 uint64_t test_cr3;
57 uint64_t test_cr4;
58 uint64_t test_dr7;
59 uint64_t test_rflags;
60 
63 
64 std::vector<gdt_x64::segment_descriptor_type> test_gdt =
65 {
66  0x0,
67  0xFF7FFFFFFFFFFFFF,
68  0xFF7FFFFFFFFFFFFF,
69  0xFF7FFFFFFFFFFFFF,
70  0xFF7FFFFFFFFFFFFF,
71  0xFF7FFFFFFFFFFFFF
72 };
73 
74 std::vector<idt_x64::interrupt_descriptor_type> test_idt = { 0x0 };
75 
76 void
78 {
79  test_gdtr.base = &test_gdt.at(0);
80  test_gdtr.limit = gsl::narrow_cast<gdt_reg_x64_t::limit_type>(test_gdt.size() *
81  sizeof(decltype(test_gdt)::value_type));
82 }
83 
84 void
86 {
87  test_idtr.base = &test_idt.at(0);
88  test_idtr.limit = gsl::narrow_cast<idt_reg_x64_t::limit_type>(test_idt.size() *
89  sizeof(decltype(test_idt)::value_type));
90 }
91 
92 extern "C" uint16_t __read_es(void) noexcept { return test_es;}
93 extern "C" uint16_t __read_cs(void) noexcept { return test_cs;}
94 extern "C" uint16_t __read_ss(void) noexcept { return test_ss;}
95 extern "C" uint16_t __read_ds(void) noexcept { return test_ds;}
96 extern "C" uint16_t __read_fs(void) noexcept { return test_fs;}
97 extern "C" uint16_t __read_gs(void) noexcept { return test_gs;}
98 extern "C" uint16_t __read_tr(void) noexcept { return test_tr;}
99 extern "C" uint16_t __read_ldtr(void) noexcept { return test_ldtr; }
100 extern "C" void __write_es(uint16_t val) noexcept { test_es = val; }
101 extern "C" void __write_cs(uint16_t val) noexcept { test_cs = val; }
102 extern "C" void __write_ss(uint16_t val) noexcept { test_ss = val; }
103 extern "C" void __write_ds(uint16_t val) noexcept { test_ds = val; }
104 extern "C" void __write_fs(uint16_t val) noexcept { test_fs = val; }
105 extern "C" void __write_gs(uint16_t val) noexcept { test_gs = val; }
106 extern "C" void __write_tr(uint16_t val) noexcept { test_tr = val; }
107 extern "C" void __write_ldtr(uint16_t val) noexcept { test_ldtr = val; }
108 
109 extern "C" uint64_t __read_cr0(void) noexcept { return test_cr0; }
110 extern "C" uint64_t __read_cr3(void) noexcept { return test_cr3; }
111 extern "C" uint64_t __read_cr4(void) noexcept { return test_cr4; }
112 extern "C" void __write_cr0(uint64_t val) noexcept { test_cr0 = val; }
113 extern "C" void __write_cr3(uint64_t val) noexcept { test_cr3 = val; }
114 extern "C" void __write_cr4(uint64_t val) noexcept { test_cr4 = val; }
115 
116 extern "C" uint64_t __read_dr7(void) noexcept { return test_dr7; }
117 extern "C" void __write_dr7(uint64_t val) noexcept { test_dr7 = val; }
118 
119 extern "C" uint64_t __read_rflags(void) noexcept { return test_rflags; }
120 
121 extern "C" void __read_gdt(gdt_reg_x64_t *gdt_reg) noexcept
122 { *gdt_reg = test_gdtr; }
123 
124 extern "C" void __read_idt(idt_reg_x64_t *idt_reg) noexcept
125 { *idt_reg = test_idtr; }
126 
127 void
128 vmcs_ut::test_host_vm_state()
129 {
130  this->expect_no_exception([&] { vmcs_intel_x64_host_vm_state state{}; });
131 }
132 
133 void
134 vmcs_ut::test_host_vm_state_segment_registers()
135 {
144 
145  this->expect_no_exception([&]
146  {
148 
149  this->expect_true(state.es() == 1U);
150  this->expect_true(state.cs() == 1U);
151  this->expect_true(state.ss() == 1U);
152  this->expect_true(state.ds() == 1U);
153  this->expect_true(state.fs() == 1U);
154  this->expect_true(state.gs() == 1U);
155  this->expect_true(state.tr() == 1U);
156  this->expect_true(state.ldtr() == 1U);
157  });
158 }
159 
160 void
161 vmcs_ut::test_host_vm_state_control_registers()
162 {
163  cr0::set(1U);
164  cr3::set(2U);
165  cr4::set(3U);
166 
167  this->expect_no_exception([&]
168  {
170 
171  this->expect_true(state.cr0() == 1U);
172  this->expect_true(state.cr3() == 2U);
173  this->expect_true(state.cr4() == (3U | cr4::vmx_enable_bit::mask));
174  });
175 }
176 
177 void
178 vmcs_ut::test_host_vm_state_debug_registers()
179 {
180  dr7::set(42U);
181 
182  this->expect_no_exception([&]
183  {
185 
186  this->expect_true(state.dr7() == 42U);
187  });
188 }
189 
190 void
191 vmcs_ut::test_host_vm_state_rflags()
192 {
193  test_rflags = 42U;
194 
195  this->expect_no_exception([&]
196  {
198 
199  this->expect_true(state.rflags() == 42U);
200  });
201 }
202 
203 void
204 vmcs_ut::test_host_vm_state_gdt_base()
205 {
206  setup_gdt();
207 
208  this->expect_no_exception([&]
209  {
211  this->expect_true(state.gdt_base() == reinterpret_cast<gdt_x64::integer_pointer>(test_gdtr.base));
212  });
213 }
214 
215 void
216 vmcs_ut::test_host_vm_state_idt_base()
217 {
218  setup_idt();
219 
220  this->expect_no_exception([&]
221  {
223  this->expect_true(state.idt_base() == reinterpret_cast<gdt_x64::integer_pointer>(test_idtr.base));
224  });
225 }
226 
227 void
228 vmcs_ut::test_host_vm_state_gdt_limit()
229 {
230  setup_gdt();
231 
232  this->expect_no_exception([&]
233  {
235  this->expect_true(state.gdt_limit() == test_gdtr.limit);
236  });
237 }
238 
239 void
240 vmcs_ut::test_host_vm_state_idt_limit()
241 {
242  setup_idt();
243 
244  this->expect_no_exception([&]
245  {
247  this->expect_true(state.idt_limit() == test_idtr.limit);
248  });
249 }
250 
251 
252 void
253 vmcs_ut::test_host_vm_state_es_limit()
254 {
255  setup_gdt();
256 
257  this->expect_no_exception([&]
258  {
261 
262  this->expect_true(state.es_limit() == 0U);
263  });
264 
265  this->expect_no_exception([&]
266  {
269 
270  this->expect_true(state.es_limit() == 0xFFFFF);
271  });
272 }
273 
274 void
275 vmcs_ut::test_host_vm_state_cs_limit()
276 {
277  setup_gdt();
278 
279  this->expect_no_exception([&]
280  {
283 
284  this->expect_true(state.cs_limit() == 0U);
285  });
286 
287  this->expect_no_exception([&]
288  {
291 
292  this->expect_true(state.cs_limit() == 0xFFFFF);
293  });
294 }
295 
296 void
297 vmcs_ut::test_host_vm_state_ss_limit()
298 {
299  setup_gdt();
300 
301  this->expect_no_exception([&]
302  {
305 
306  this->expect_true(state.ss_limit() == 0U);
307  });
308 
309  this->expect_no_exception([&]
310  {
313 
314  this->expect_true(state.ss_limit() == 0xFFFFF);
315  });
316 }
317 
318 void
319 vmcs_ut::test_host_vm_state_ds_limit()
320 {
321  setup_gdt();
322 
323  this->expect_no_exception([&]
324  {
327 
328  this->expect_true(state.ds_limit() == 0U);
329  });
330 
331  this->expect_no_exception([&]
332  {
335 
336  this->expect_true(state.ds_limit() == 0xFFFFF);
337  });
338 }
339 
340 void
341 vmcs_ut::test_host_vm_state_fs_limit()
342 {
343  setup_gdt();
344 
345  this->expect_no_exception([&]
346  {
349 
350  this->expect_true(state.fs_limit() == 0U);
351  });
352 
353  this->expect_no_exception([&]
354  {
357 
358  this->expect_true(state.fs_limit() == 0xFFFFF);
359  });
360 }
361 
362 void
363 vmcs_ut::test_host_vm_state_gs_limit()
364 {
365  setup_gdt();
366 
367  this->expect_no_exception([&]
368  {
371 
372  this->expect_true(state.gs_limit() == 0U);
373  });
374 
375  this->expect_no_exception([&]
376  {
379 
380  this->expect_true(state.gs_limit() == 0xFFFFF);
381  });
382 }
383 
384 void
385 vmcs_ut::test_host_vm_state_tr_limit()
386 {
387  setup_gdt();
388 
389  this->expect_no_exception([&]
390  {
393 
394  this->expect_true(state.tr_limit() == 0U);
395  });
396 
397  this->expect_no_exception([&]
398  {
401 
402  this->expect_true(state.tr_limit() == 0xFFFFF);
403  });
404 }
405 
406 void
407 vmcs_ut::test_host_vm_state_ldtr_limit()
408 {
409  setup_gdt();
410 
411  this->expect_no_exception([&]
412  {
415 
416  this->expect_true(state.ldtr_limit() == 0U);
417  });
418 
419  this->expect_no_exception([&]
420  {
423 
424  this->expect_true(state.ldtr_limit() == 0xFFFFF);
425  });
426 }
427 
428 void
429 vmcs_ut::test_host_vm_state_es_access_rights()
430 {
431  setup_gdt();
432 
433  this->expect_no_exception([&]
434  {
437 
438  this->expect_true(state.es_access_rights() == x64::access_rights::unusable);
439  });
440 
441  this->expect_no_exception([&]
442  {
445 
446  this->expect_true(state.es_access_rights() == 0x70FF);
447  });
448 }
449 
450 void
451 vmcs_ut::test_host_vm_state_cs_access_rights()
452 {
453  setup_gdt();
454 
455  this->expect_no_exception([&]
456  {
459 
460  this->expect_true(state.cs_access_rights() == x64::access_rights::unusable);
461  });
462 
463  this->expect_no_exception([&]
464  {
467 
468  this->expect_true(state.cs_access_rights() == 0x70FF);
469  });
470 }
471 
472 void
473 vmcs_ut::test_host_vm_state_ss_access_rights()
474 {
475  setup_gdt();
476 
477  this->expect_no_exception([&]
478  {
481 
482  this->expect_true(state.ss_access_rights() == x64::access_rights::unusable);
483  });
484 
485  this->expect_no_exception([&]
486  {
489 
490  this->expect_true(state.ss_access_rights() == 0x70FF);
491  });
492 }
493 
494 void
495 vmcs_ut::test_host_vm_state_ds_access_rights()
496 {
497  setup_gdt();
498 
499  this->expect_no_exception([&]
500  {
503 
504  this->expect_true(state.ds_access_rights() == x64::access_rights::unusable);
505  });
506 
507  this->expect_no_exception([&]
508  {
511 
512  this->expect_true(state.ds_access_rights() == 0x70FF);
513  });
514 }
515 
516 void
517 vmcs_ut::test_host_vm_state_fs_access_rights()
518 {
519  setup_gdt();
520 
521  this->expect_no_exception([&]
522  {
525 
526  this->expect_true(state.fs_access_rights() == x64::access_rights::unusable);
527  });
528 
529  this->expect_no_exception([&]
530  {
533 
534  this->expect_true(state.fs_access_rights() == 0x70FF);
535  });
536 }
537 
538 void
539 vmcs_ut::test_host_vm_state_gs_access_rights()
540 {
541  setup_gdt();
542 
543  this->expect_no_exception([&]
544  {
547 
548  this->expect_true(state.gs_access_rights() == x64::access_rights::unusable);
549  });
550 
551  this->expect_no_exception([&]
552  {
555 
556  this->expect_true(state.gs_access_rights() == 0x70FF);
557  });
558 }
559 
560 void
561 vmcs_ut::test_host_vm_state_tr_access_rights()
562 {
563  setup_gdt();
564 
565  this->expect_no_exception([&]
566  {
569 
570  this->expect_true(state.tr_access_rights() == x64::access_rights::unusable);
571  });
572 
573  this->expect_no_exception([&]
574  {
577 
578  this->expect_true(state.tr_access_rights() == 0x70FF);
579  });
580 }
581 
582 void
583 vmcs_ut::test_host_vm_state_ldtr_access_rights()
584 {
585  setup_gdt();
586 
587  this->expect_no_exception([&]
588  {
591 
592  this->expect_true(state.ldtr_access_rights() == x64::access_rights::unusable);
593  });
594 
595  this->expect_no_exception([&]
596  {
599 
600  this->expect_true(state.ldtr_access_rights() == 0x70FF);
601  });
602 }
603 
604 void
605 vmcs_ut::test_host_vm_state_es_base()
606 {
607  setup_gdt();
608 
609  this->expect_no_exception([&]
610  {
613 
614  this->expect_true(state.es_base() == 0U);
615  });
616 
617  this->expect_no_exception([&]
618  {
621 
622  this->expect_true(state.es_base() == 0xFFFFFFFF);
623  });
624 }
625 
626 void
627 vmcs_ut::test_host_vm_state_cs_base()
628 {
629  setup_gdt();
630 
631  this->expect_no_exception([&]
632  {
635 
636  this->expect_true(state.cs_base() == 0U);
637  });
638 
639  this->expect_no_exception([&]
640  {
643 
644  this->expect_true(state.cs_base() == 0xFFFFFFFF);
645  });
646 }
647 
648 void
649 vmcs_ut::test_host_vm_state_ss_base()
650 {
651  setup_gdt();
652 
653  this->expect_no_exception([&]
654  {
657 
658  this->expect_true(state.ss_base() == 0U);
659  });
660 
661  this->expect_no_exception([&]
662  {
665 
666  this->expect_true(state.ss_base() == 0xFFFFFFFF);
667  });
668 }
669 
670 void
671 vmcs_ut::test_host_vm_state_ds_base()
672 {
673  setup_gdt();
674 
675  this->expect_no_exception([&]
676  {
679 
680  this->expect_true(state.ds_base() == 0U);
681  });
682 
683  this->expect_no_exception([&]
684  {
687 
688  this->expect_true(state.ds_base() == 0xFFFFFFFF);
689  });
690 }
691 
692 void
693 vmcs_ut::test_host_vm_state_fs_base()
694 {
695  setup_gdt();
696 
697  this->expect_no_exception([&]
698  {
701 
702  this->expect_true(state.fs_base() == 0U);
703  });
704 
705  this->expect_no_exception([&]
706  {
709 
710  this->expect_true(state.fs_base() == 0xFFFFFFFF);
711  });
712 }
713 
714 void
715 vmcs_ut::test_host_vm_state_gs_base()
716 {
717  setup_gdt();
718 
719  this->expect_no_exception([&]
720  {
723 
724  this->expect_true(state.gs_base() == 0U);
725  });
726 
727  this->expect_no_exception([&]
728  {
731 
732  this->expect_true(state.gs_base() == 0xFFFFFFFF);
733  });
734 }
735 
736 void
737 vmcs_ut::test_host_vm_state_tr_base()
738 {
739  setup_gdt();
740 
741  this->expect_no_exception([&]
742  {
745 
746  this->expect_true(state.tr_base() == 0U);
747  });
748 
749  this->expect_no_exception([&]
750  {
753 
754  this->expect_true(state.tr_base() == 0xFFFFFFFF);
755  });
756 }
757 
758 void
759 vmcs_ut::test_host_vm_state_ldtr_base()
760 {
761  setup_gdt();
762 
763  this->expect_no_exception([&]
764  {
767 
768  this->expect_true(state.ldtr_base() == 0U);
769  });
770 
771  this->expect_no_exception([&]
772  {
775 
776  this->expect_true(state.ldtr_base() == 0xFFFFFFFF);
777  });
778 }
779 
780 void
781 vmcs_ut::test_host_vm_state_ia32_msrs_with_perf_global_ctrl()
782 {
783  g_eax_cpuid[0xA] = 2;
784 
794 
795  this->expect_no_exception([&]
796  {
798 
799  this->expect_true(state.ia32_debugctl_msr() == 42U);
800  this->expect_true(state.ia32_pat_msr() == 42U);
801  this->expect_true(state.ia32_efer_msr() == 42U);
802  this->expect_true(state.ia32_perf_global_ctrl_msr() == 42U);
803  this->expect_true(state.ia32_sysenter_cs_msr() == 42U);
804  this->expect_true(state.ia32_sysenter_esp_msr() == 42U);
805  this->expect_true(state.ia32_sysenter_eip_msr() == 42U);
806  this->expect_true(state.ia32_fs_base_msr() == 42U);
807  this->expect_true(state.ia32_gs_base_msr() == 42U);
808  });
809 }
810 
811 void
812 vmcs_ut::test_host_vm_state_ia32_msrs_without_perf_global_ctrl()
813 {
814  g_eax_cpuid[0xA] = 1;
815 
824 
825  this->expect_no_exception([&]
826  {
828 
829  this->expect_true(state.ia32_debugctl_msr() == 42U);
830  this->expect_true(state.ia32_pat_msr() == 42U);
831  this->expect_true(state.ia32_efer_msr() == 42U);
832  this->expect_true(state.ia32_sysenter_cs_msr() == 42U);
833  this->expect_true(state.ia32_sysenter_esp_msr() == 42U);
834  this->expect_true(state.ia32_sysenter_eip_msr() == 42U);
835  this->expect_true(state.ia32_fs_base_msr() == 42U);
836  this->expect_true(state.ia32_gs_base_msr() == 42U);
837  });
838 }
839 
840 void
841 vmcs_ut::test_host_vm_state_dump()
842 {
843  this->expect_no_exception([&]
844  {
846  this->expect_no_exception([&] { state.dump(); });
847  });
848 }
void set(T val) noexcept
Definition: srs_x64.h:405
uint16_t __read_cs(void) noexcept
uint16_t limit_type
Definition: idt_x64.h:41
base_type base
Definition: gdt_x64.h:45
void set(T val) noexcept
Definition: srs_x64.h:213
void set(T val) noexcept
Definition: srs_x64.h:165
void __write_gs(uint16_t val) noexcept
void set(T val) noexcept
Definition: debug_x64.h:40
void __write_cr4(uint64_t val) noexcept
void set(T val) noexcept
Definition: srs_x64.h:299
void set(T val) noexcept
Definition: srs_x64.h:443
uint16_t __read_ds(void) noexcept
uint64_t __read_rflags(void) noexcept
void __write_ldtr(uint16_t val) noexcept
std::vector< gdt_x64::segment_descriptor_type > test_gdt
void set(T val) noexcept
Definition: srs_x64.h:357
std::vector< idt_x64::interrupt_descriptor_type > test_idt
#define expect_no_exception(f)
Definition: unittest.h:198
constexpr const auto mask
Definition: cpuid_x64.h:85
uint64_t __read_dr7(void) noexcept
void set(T val) noexcept
Definition: srs_x64.h:69
void set(T val) noexcept
Definition: msrs_x64.h:57
uint16_t __read_ldtr(void) noexcept
void __write_cr0(uint64_t val) noexcept
void __write_cr3(uint64_t val) noexcept
void __read_idt(idt_reg_x64_t *idt_reg) noexcept
void __write_fs(uint16_t val) noexcept
constexpr const auto unusable
Definition: x64.h:90
void set(T val) noexcept
Definition: srs_x64.h:117
uint32_t value_type
Definition: cpuid_x64.h:41
gdt_reg_x64_t test_gdtr
uint16_t limit_type
Definition: gdt_x64.h:41
idt_reg_x64_t test_idtr
base_type base
Definition: idt_x64.h:45
void set(T val) noexcept
Definition: srs_x64.h:203
void uint64_t uint64_t uint64_t *rdx noexcept
std::map< cpuid::field_type, cpuid::value_type > g_eax_cpuid
void set(T val) noexcept
Definition: srs_x64.h:395
limit_type limit
Definition: idt_x64.h:44
void __write_ss(uint16_t val) noexcept
void set(T val) noexcept
void set(T val) noexcept
Definition: srs_x64.h:261
void __write_es(uint16_t val) noexcept
void __write_ds(uint16_t val) noexcept
uint64_t __read_cr3(void) noexcept
void __write_tr(uint16_t val) noexcept
void __read_gdt(gdt_reg_x64_t *gdt_reg) noexcept
uint16_t __read_ss(void) noexcept
uint64_t __read_cr0(void) noexcept
uint16_t __read_es(void) noexcept
void set(T val) noexcept
Definition: srs_x64.h:155
void set(T val) noexcept
Definition: srs_x64.h:347
void __write_cs(uint16_t val) noexcept
uint16_t __read_gs(void) noexcept
void set(T val) noexcept
Definition: srs_x64.h:309
uint16_t __read_tr(void) noexcept
uint16_t __read_fs(void) noexcept
uint64_t __read_cr4(void) noexcept
void set(T val) noexcept
Definition: crs_intel_x64.h:52
Definition: cache_x64.h:31
void set(T val) noexcept
Definition: srs_x64.h:251
uintptr_t integer_pointer
Definition: gdt_x64.h:196
void __write_dr7(uint64_t val) noexcept
limit_type limit
Definition: gdt_x64.h:44
void set(T val) noexcept
Definition: srs_x64.h:107
#define expect_true(a)