forked from ionescu007/SimpleVisor
-
Notifications
You must be signed in to change notification settings - Fork 1
/
shvutil.c
96 lines (76 loc) · 2.47 KB
/
shvutil.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*++
Copyright (c) Alex Ionescu. All rights reserved.
Module Name:
shvutil.c
Abstract:
This module implements utility functions for the Simple Hyper Visor.
Author:
Alex Ionescu (@aionescu) 16-Mar-2016 - Initial version
Environment:
Kernel mode only.
--*/
#include "shv.h"
VOID
ShvUtilConvertGdtEntry (
_In_ PVOID GdtBase,
_In_ USHORT Selector,
_Out_ PVMX_GDTENTRY64 VmxGdtEntry
)
{
PKGDTENTRY64 gdtEntry;
//
// Read the GDT entry at the given selector, masking out the RPL bits. x64
// Windows does not use an LDT for these selectors in kernel, so the TI bit
// should never be set.
//
NT_ASSERT((Selector & SELECTOR_TABLE_INDEX) == 0);
gdtEntry = (PKGDTENTRY64)((ULONG_PTR)GdtBase + (Selector & ~RPL_MASK));
//
// Write the selector directly
//
VmxGdtEntry->Selector = Selector;
//
// Use the LSL intrinsic to read the segment limit
//
VmxGdtEntry->Limit = __segmentlimit(Selector);
//
// Build the full 64-bit effective address, keeping in mind that only when
// the System bit is unset, should this be done.
//
// NOTE: The Windows definition of KGDTENTRY64 is WRONG. The "System" field
// is incorrectly defined at the position of where the AVL bit should be.
// The actual location of the SYSTEM bit is encoded as the highest bit in
// the "Type" field.
//
VmxGdtEntry->Base = ((gdtEntry->Bytes.BaseHigh << 24) |
(gdtEntry->Bytes.BaseMiddle << 16) |
(gdtEntry->BaseLow)) & MAXULONG;
VmxGdtEntry->Base |= ((gdtEntry->Bits.Type & 0x10) == 0) ?
((ULONG_PTR)gdtEntry->BaseUpper << 32) : 0;
//
// Load the access rights
//
VmxGdtEntry->AccessRights = 0;
VmxGdtEntry->Bytes.Flags1 = gdtEntry->Bytes.Flags1;
VmxGdtEntry->Bytes.Flags2 = gdtEntry->Bytes.Flags2;
//
// Finally, handle the VMX-specific bits
//
VmxGdtEntry->Bits.Reserved = 0;
VmxGdtEntry->Bits.Unusable = !gdtEntry->Bits.Present;
}
ULONG
ShvUtilAdjustMsr (
_In_ LARGE_INTEGER ControlValue,
_In_ ULONG DesiredValue
)
{
//
// VMX feature/capability MSRs encode the "must be 0" bits in the high word
// of their value, and the "must be 1" bits in the low word of their value.
// Adjust any requested capability/feature based on these requirements.
//
DesiredValue &= ControlValue.HighPart;
DesiredValue |= ControlValue.LowPart;
return DesiredValue;
}