HyperDbg Debugger
Loading...
Searching...
No Matches
MsrHandlers.c File Reference

Handle for MSR-related tasks in VMX-root. More...

#include "pch.h"

Functions

BOOLEAN MsrHandleIsHypervSyntheticMsr (_In_ UINT32 TargetMsr)
 Checks whether an MSR belongs to the Hyper-V synthetic MSR set.
VOID MsrHandleRdmsrVmexit (VIRTUAL_MACHINE_STATE *VCpu)
 Handles in the cases when RDMSR causes a vm-exit.
VOID MsrHandleWrmsrVmexit (VIRTUAL_MACHINE_STATE *VCpu)
 Handles in the cases when RDMSR causes a vm-exit.
BOOLEAN MsrHandleSetMsrBitmap (VIRTUAL_MACHINE_STATE *VCpu, UINT32 Msr, BOOLEAN ReadDetection, BOOLEAN WriteDetection)
 Set bits in Msr Bitmap.
BOOLEAN MsrHandleUnSetMsrBitmap (VIRTUAL_MACHINE_STATE *VCpu, UINT32 Msr, BOOLEAN ReadDetection, BOOLEAN WriteDetection)
 UnSet bits in Msr Bitmap.
VOID MsrHandleFilterMsrReadBitmap (VIRTUAL_MACHINE_STATE *VCpu)
 Filter to avoid msr set for MSRs that are not valid or should be ignored (RDMSR).
VOID MsrHandleFilterMsrWriteBitmap (VIRTUAL_MACHINE_STATE *VCpu)
 Filter to avoid msr set for MSRs that are not valid or should be ignored (wrmsr).
VOID MsrHandlePerformMsrBitmapReadChange (VIRTUAL_MACHINE_STATE *VCpu, UINT32 MsrMask)
 Change MSR Bitmap for read.
VOID MsrHandlePerformMsrBitmapReadReset (VIRTUAL_MACHINE_STATE *VCpu)
 Reset MSR Bitmap for read.
VOID MsrHandlePerformMsrBitmapWriteChange (VIRTUAL_MACHINE_STATE *VCpu, UINT32 MsrMask)
 Change MSR Bitmap for write.
VOID MsrHandlePerformMsrBitmapWriteReset (VIRTUAL_MACHINE_STATE *VCpu)
 Reset MSR Bitmap for write.

Detailed Description

Handle for MSR-related tasks in VMX-root.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.1
Date
2021-12-24

Function Documentation

◆ MsrHandleFilterMsrReadBitmap()

VOID MsrHandleFilterMsrReadBitmap ( VIRTUAL_MACHINE_STATE * VCpu)

Filter to avoid msr set for MSRs that are not valid or should be ignored (RDMSR).

Parameters
VCpuThe virtual processor's state
Returns
VOID
468{
469 //
470 // Ignore IA32_KERNEL_GSBASE (0xC0000102)
471 //
472 ClearBit(0x102, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 1024));
473
474 //
475 // Ignore IA32_MPERF (0x000000e7), and IA32_APERF (0x000000e8)
476 //
477 ClearBit(0xe7, (ULONG *)VCpu->MsrBitmapVirtualAddress);
478 ClearBit(0xe8, (ULONG *)VCpu->MsrBitmapVirtualAddress);
479}
VOID ClearBit(INT BitNumber, ULONG *Addr)
unset the bit
Definition Bitwise.c:34
unsigned long ULONG
Definition BasicTypes.h:31
UINT64 MsrBitmapVirtualAddress
Definition State.h:337

◆ MsrHandleFilterMsrWriteBitmap()

VOID MsrHandleFilterMsrWriteBitmap ( VIRTUAL_MACHINE_STATE * VCpu)

Filter to avoid msr set for MSRs that are not valid or should be ignored (wrmsr).

Parameters
VCpuThe virtual processor's state
Returns
VOID
490{
491 //
492 // Ignore IA32_KERNEL_GSBASE (0xC0000102)
493 //
494 ClearBit(0x102, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 3072));
495
496 //
497 // Ignore IA32_MPERF (0x000000e7), and IA32_APERF (0x000000e8)
498 //
499 ClearBit(0xe7, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
500 ClearBit(0xe8, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
501
502 //
503 // Ignore IA32_SPEC_CTRL (0x00000048), and IA32_PRED_CMD (0x00000049)
504 //
505 ClearBit(0x48, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
506 ClearBit(0x49, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
507}

◆ MsrHandleIsHypervSyntheticMsr()

BOOLEAN MsrHandleIsHypervSyntheticMsr ( _In_ UINT32 TargetMsr)

Checks whether an MSR belongs to the Hyper-V synthetic MSR set.

The ranges and individual registers are defined by Hyper-V TLFS synthetic MSRs and mirrored in HypervTlfs.h.

Parameters
TargetMsrThe target MSR
Returns
BOOLEAN Returns TRUE if the MSR should be forwarded to the top-level Hyper-V compatible hypervisor
25{
26 switch (TargetMsr)
27 {
45 return TRUE;
46 default:
47 return (TargetMsr >= HV_X64_MSR_EOI && TargetMsr <= HV_X64_MSR_TPR) ||
48 (TargetMsr >= HV_X64_MSR_SCONTROL && TargetMsr <= HV_X64_MSR_EOM) ||
49 (TargetMsr >= HV_X64_MSR_SINT0 && TargetMsr <= HV_X64_MSR_SINT15) ||
50 (TargetMsr >= HV_X64_MSR_STIMER0_CONFIG && TargetMsr <= HV_X64_MSR_STIMER3_COUNT) ||
51 (TargetMsr >= HV_X64_MSR_CRASH_P0 && TargetMsr <= HV_X64_MSR_CRASH_CTL) ||
52 (TargetMsr >= HV_X64_MSR_NESTED_SCONTROL && TargetMsr <= HV_X64_MSR_NESTED_EOM) ||
53 (TargetMsr >= HV_X64_MSR_NESTED_SINT0 && TargetMsr <= HV_X64_MSR_NESTED_SINT15);
54 }
55}
#define HV_X64_MSR_TIME_REF_COUNT
Definition HypervTlfs.h:296
#define HV_X64_MSR_APIC_FREQUENCY
Definition HypervTlfs.h:188
#define HV_X64_MSR_TSC_EMULATION_STATUS
Definition HypervTlfs.h:268
#define HV_X64_MSR_NESTED_SINT15
Definition HypervTlfs.h:240
#define HV_X64_MSR_STIME_UNHALTED_TIMER_COUNT
Definition HypervTlfs.h:235
#define HV_X64_MSR_EOM
Definition HypervTlfs.h:287
#define HV_X64_MSR_STIMER0_CONFIG
Definition HypervTlfs.h:275
#define HV_X64_MSR_SCONTROL
Definition HypervTlfs.h:282
#define HV_X64_MSR_EOI
Definition HypervTlfs.h:191
#define HV_X64_MSR_REFERENCE_TSC
Definition HypervTlfs.h:297
#define HV_X64_MSR_TPR
Definition HypervTlfs.h:193
#define HV_X64_MSR_CRASH_CTL
Definition HypervTlfs.h:295
#define HV_X64_MSR_NESTED_SINT0
Definition HypervTlfs.h:239
#define HV_X64_MSR_GUEST_OS_ID
Definition HypervTlfs.h:164
#define HV_X64_MSR_VP_RUNTIME
Definition HypervTlfs.h:176
#define HV_X64_MSR_CRASH_P0
Definition HypervTlfs.h:290
#define HV_X64_MSR_NESTED_VP_INDEX
Definition HypervTlfs.h:236
#define HV_X64_MSR_REENLIGHTENMENT_CONTROL
Definition HypervTlfs.h:266
#define HV_X64_MSR_SINT0
Definition HypervTlfs.h:288
#define HV_X64_MSR_NESTED_SCONTROL
Definition HypervTlfs.h:237
#define HV_X64_MSR_RESET
Definition HypervTlfs.h:173
#define HV_X64_MSR_NESTED_EOM
Definition HypervTlfs.h:238
#define HV_X64_MSR_STIMER3_COUNT
Definition HypervTlfs.h:280
#define HV_X64_MSR_VP_INDEX
Definition HypervTlfs.h:286
#define HV_X64_MSR_TSC_FREQUENCY
Definition HypervTlfs.h:185
#define HV_X64_MSR_GUEST_IDLE
Definition HypervTlfs.h:255
#define HV_X64_MSR_STIME_UNHALTED_TIMER_CONFIG
Definition HypervTlfs.h:234
#define HV_X64_MSR_NPIEP_CONFIG
Definition HypervTlfs.h:221
#define HV_X64_MSR_SINT15
Definition HypervTlfs.h:289
#define HV_X64_MSR_TSC_EMULATION_CONTROL
Definition HypervTlfs.h:267
#define HV_X64_MSR_HYPERCALL
Definition HypervTlfs.h:167
#define TRUE
Definition BasicTypes.h:114

◆ MsrHandlePerformMsrBitmapReadChange()

VOID MsrHandlePerformMsrBitmapReadChange ( VIRTUAL_MACHINE_STATE * VCpu,
UINT32 MsrMask )

Change MSR Bitmap for read.

should be called in vmx-root mode

Parameters
VCpuThe virtual processor's state
MsrMask
Returns
VOID
519{
521 {
522 //
523 // Means all the bitmaps should be put to 1
524 //
525 memset((PVOID)VCpu->MsrBitmapVirtualAddress, 0xff, 2048);
526
527 //
528 // Filter MSR Bitmap for special MSRs
529 //
531 }
532 else
533 {
534 //
535 // Means only one msr bitmap is target
536 //
537 MsrHandleSetMsrBitmap(VCpu, MsrMask, TRUE, FALSE);
538 }
539}
BOOLEAN MsrHandleSetMsrBitmap(VIRTUAL_MACHINE_STATE *VCpu, UINT32 Msr, BOOLEAN ReadDetection, BOOLEAN WriteDetection)
Set bits in Msr Bitmap.
Definition MsrHandlers.c:371
VOID MsrHandleFilterMsrReadBitmap(VIRTUAL_MACHINE_STATE *VCpu)
Filter to avoid msr set for MSRs that are not valid or should be ignored (RDMSR).
Definition MsrHandlers.c:467
void * PVOID
Definition BasicTypes.h:56
#define FALSE
Definition BasicTypes.h:113
#define DEBUGGER_EVENT_MSR_READ_OR_WRITE_ALL_MSRS
Apply to all Model Specific Registers.
Definition Constants.h:751

◆ MsrHandlePerformMsrBitmapReadReset()

VOID MsrHandlePerformMsrBitmapReadReset ( VIRTUAL_MACHINE_STATE * VCpu)

Reset MSR Bitmap for read.

should be called in vmx-root mode

Parameters
VCpuThe virtual processor's state
Returns
VOID
550{
551 //
552 // Means all the bitmaps should be put to 0
553 //
554 memset((PVOID)VCpu->MsrBitmapVirtualAddress, 0x0, 2048);
555}

◆ MsrHandlePerformMsrBitmapWriteChange()

VOID MsrHandlePerformMsrBitmapWriteChange ( VIRTUAL_MACHINE_STATE * VCpu,
UINT32 MsrMask )

Change MSR Bitmap for write.

should be called in vmx-root mode

Parameters
VCpuThe virtual processor's state
MsrMaskMSR
Returns
VOID
566{
568 {
569 //
570 // Means all the bitmaps should be put to 1
571 //
572 memset((PVOID)((UINT64)VCpu->MsrBitmapVirtualAddress + 2048), 0xff, 2048);
573
574 //
575 // Filter MSR Bitmap for special MSRs
576 //
578 }
579 else
580 {
581 //
582 // Means only one msr bitmap is target
583 //
584 MsrHandleSetMsrBitmap(VCpu, MsrMask, FALSE, TRUE);
585 }
586}
VOID MsrHandleFilterMsrWriteBitmap(VIRTUAL_MACHINE_STATE *VCpu)
Filter to avoid msr set for MSRs that are not valid or should be ignored (wrmsr).
Definition MsrHandlers.c:489

◆ MsrHandlePerformMsrBitmapWriteReset()

VOID MsrHandlePerformMsrBitmapWriteReset ( VIRTUAL_MACHINE_STATE * VCpu)

Reset MSR Bitmap for write.

should be called in vmx-root mode

Parameters
VCpuThe virtual processor's state
Returns
VOID
597{
598 //
599 // Means all the bitmaps should be put to 0
600 //
601 memset((PVOID)((UINT64)VCpu->MsrBitmapVirtualAddress + 2048), 0x0, 2048);
602}

◆ MsrHandleRdmsrVmexit()

VOID MsrHandleRdmsrVmexit ( VIRTUAL_MACHINE_STATE * VCpu)

Handles in the cases when RDMSR causes a vm-exit.

Parameters
VCpuThe virtual processor's state
Returns
VOID
66{
67 UINT32 TargetMsr;
68 MSR Msr = {0};
69 PGUEST_REGS GuestRegs = VCpu->Regs;
70
71 //
72 // RDMSR. The RDMSR instruction causes a VM exit if any of the following are true:
73 //
74 // The "use MSR bitmaps" VM-execution control is 0.
75 // The value of ECX is not in the ranges 00000000H - 00001FFFH and C0000000H - C0001FFFH
76 // The value of ECX is in the range 00000000H - 00001FFFH and bit n in read bitmap for low MSRs is 1,
77 // where n is the value of ECX.
78 // The value of ECX is in the range C0000000H - C0001FFFH and bit n in read bitmap for high MSRs is 1,
79 // where n is the value of ECX & 00001FFFH.
80 //
81 TargetMsr = GuestRegs->rcx & 0xffffffff;
82
83 //
84 // Execute WRMSR or RDMSR on behalf of the guest. Important that this
85 // can cause bug check when the guest tries to access unimplemented MSR
86 // even within the SEH block* because the below WRMSR or RDMSR raises
87 // #GP and are not protected by the SEH block (or cannot be protected
88 // either as this code run outside the thread stack region Windows
89 // requires to proceed SEH). Hypervisors typically handle this by noop-ing
90 // WRMSR and returning zero for RDMSR with non-architecturally defined
91 // MSRs. Alternatively, one can probe which MSRs should cause #GP prior
92 // to installation of a hypervisor and the hypervisor can emulate the
93 // results.
94 //
95
96 // LogInfo("MSR read (RDMSR) VM-exit, MSR: %x, from: %llx",
97 // TargetMsr,
98 // VCpu->LastVmexitRip);
99
100 //
101 // Checking whether it is a synthetic MSR for Hyper-V
102 //
104 {
105 Msr.Flags = CpuReadMsr(TargetMsr);
106
107 GuestRegs->rax = Msr.Fields.Low;
108 GuestRegs->rdx = Msr.Fields.High;
109
110 return;
111 }
112
113 //
114 // Check for sanity of MSR if they're valid or they're for reserved range for WRMSR and RDMSR
115 //
116 if ((TargetMsr <= 0x00001FFF) || ((0xC0000000 <= TargetMsr) && (TargetMsr <= 0xC0001FFF)) ||
117 (TargetMsr >= RESERVED_MSR_RANGE_LOW && (TargetMsr <= RESERVED_MSR_RANGE_HI)))
118 {
119 //
120 // Apply the RDMS
121 //
122 switch (TargetMsr)
123 {
124 case IA32_SYSENTER_CS:
125 VmxVmread64P(VMCS_GUEST_SYSENTER_CS, &Msr.Flags);
126 break;
127
128 case IA32_SYSENTER_ESP:
129 VmxVmread64P(VMCS_GUEST_SYSENTER_ESP, &Msr.Flags);
130 break;
131
132 case IA32_SYSENTER_EIP:
133 VmxVmread64P(VMCS_GUEST_SYSENTER_EIP, &Msr.Flags);
134 break;
135
136 case IA32_GS_BASE:
137 VmxVmread64P(VMCS_GUEST_GS_BASE, &Msr.Flags);
138 break;
139
140 case IA32_FS_BASE:
141 VmxVmread64P(VMCS_GUEST_FS_BASE, &Msr.Flags);
142 break;
143
145
146 //
147 // VMware workstation and Hyper-V use this MSR halt the system
148 // Read more:
149 // https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/vp-properties#virtual-processor-idle-sleep-state
150 // As a top-level hypervisor, we get this MSRs VM-exit (even
151 // without setting MSR bitmap because this MSR is not a valid
152 // range MSR).
153 //
154 // This behavior is problematic for the debugger when we throw an NMI
155 // to halt all of the cores, if the core already executed RDMSR on this MSR,
156 // we'll end up notifying the core in VMX root-root (this is the expected
157 // behavior); however, after continuing the guest, we still won't get a
158 // chance to continue execution. Thus, all of the cores remain unlocked (in
159 // debuggee) and halted. So, we cannot send commands to them, and later when
160 // we continue the guest, and the guest tries to perform the steps necessary for
161 // locking, which is not expected and eventually causes a BSOD.
162 //
163 // As a quick and dirty patch (which is not a good idea for power-saving
164 // and performance reasons), we ignored these MSRs.
165 //
166 break;
167
168 default:
169
170 //
171 // Check whether the MSR should cause #GP or not
172 //
173 if (TargetMsr <= 0xfff && TestBit(TargetMsr, (ULONG *)g_MsrBitmapInvalidMsrs) != NULL64_ZERO)
174 {
175 //
176 // Invalid MSR between 0x0 to 0xfff
177 //
179 return;
180 }
181
182 //
183 // Check for the footprints of the RDMSR in the transparent mode
184 //
186 {
187 return;
188 }
189
190 //
191 // Msr is valid
192 //
193 Msr.Flags = CpuReadMsr(TargetMsr);
194
195 //
196 // Check if it's EFER MSR then we show a false SCE state
197 //
198 if (GuestRegs->rcx == IA32_EFER)
199 {
200 IA32_EFER_REGISTER MsrEFER;
201 MsrEFER.AsUInt = Msr.Flags;
202 MsrEFER.SyscallEnable = TRUE;
203 Msr.Flags = MsrEFER.AsUInt;
204 }
205
206 break;
207 }
208
209 GuestRegs->rax = NULL64_ZERO;
210 GuestRegs->rdx = NULL64_ZERO;
211
212 GuestRegs->rax = Msr.Fields.Low;
213 GuestRegs->rdx = Msr.Fields.High;
214 }
215 else
216 {
217 //
218 // MSR is invalid, inject #GP
219 //
221 return;
222 }
223}
INT TestBit(INT BitNumber, ULONG *Addr)
Check whether the bit is set or not.
Definition Bitwise.c:22
VOID EventInjectGeneralProtection()
Inject GP to the guest (Event Injection).
Definition Events.c:62
union _MSR MSR
General MSR Structure.
BOOLEAN MsrHandleIsHypervSyntheticMsr(_In_ UINT32 TargetMsr)
Checks whether an MSR belongs to the Hyper-V synthetic MSR set.
Definition MsrHandlers.c:24
UINT64 CpuReadMsr(ULONG MsrAddress)
Read an MSR.
Definition PlatformIntrinsics.c:213
UCHAR VmxVmread64P(size_t Field, UINT64 *FieldValue)
VMX VMREAD instruction (64-bit, pointer variant).
Definition PlatformIntrinsicsVmx.c:207
struct GUEST_REGS * PGUEST_REGS
#define NULL64_ZERO
Definition BasicTypes.h:111
unsigned int UINT32
Definition BasicTypes.h:54
#define RESERVED_MSR_RANGE_LOW
Hypervisor reserved range for RDMSR and WRMSR.
Definition Constants.h:707
#define RESERVED_MSR_RANGE_HI
Definition Constants.h:708
IMPORT_EXPORT_HYPEREVADE BOOLEAN TransparentCheckAndModifyMsrRead(PGUEST_REGS Regs, UINT32 TargetMsr)
Handle RDMSR VM exits when the Transparent mode is enabled.
Definition VmxFootprints.c:57
BOOLEAN g_IsTopLevelHypervisorHyperV
Whether the top level hypervisor is Hyper-V or not.
Definition GlobalVariables.h:220
UINT64 * g_MsrBitmapInvalidMsrs
Bitmap of MSRs that cause GP.
Definition GlobalVariables.h:100
BOOLEAN g_CheckForFootprints
Shows whether the footprints (anti-debugging and anti-hypervisor) should be checked or not.
Definition GlobalVariables.h:131
GUEST_REGS * Regs
Definition State.h:326
UINT64 rax
Definition BasicTypes.h:141
UINT64 rcx
Definition BasicTypes.h:142
UINT64 rdx
Definition BasicTypes.h:143
UINT64 Flags
Definition Msr.h:42
ULONG Low
Definition Msr.h:38
struct _MSR::@027346114345265205246155043220371021005105071041 Fields
ULONG High
Definition Msr.h:39

◆ MsrHandleSetMsrBitmap()

BOOLEAN MsrHandleSetMsrBitmap ( VIRTUAL_MACHINE_STATE * VCpu,
UINT32 Msr,
BOOLEAN ReadDetection,
BOOLEAN WriteDetection )

Set bits in Msr Bitmap.

Parameters
VCpuThe virtual processor's state
MsrMSR Address
ReadDetectionset read bit
WriteDetectionset write bit
Returns
BOOLEAN Returns true if the MSR Bitmap is successfully applied or false if not applied
372{
373 if (!ReadDetection && !WriteDetection)
374 {
375 //
376 // Invalid Command
377 //
378 return FALSE;
379 }
380
381 if (Msr <= 0x00001FFF)
382 {
383 if (ReadDetection)
384 {
385 SetBit(Msr, (ULONG *)VCpu->MsrBitmapVirtualAddress);
386 }
387 if (WriteDetection)
388 {
389 SetBit(Msr, (ULONG *)VCpu->MsrBitmapVirtualAddress + 2048);
390 }
391 }
392 else if ((0xC0000000 <= Msr) && (Msr <= 0xC0001FFF))
393 {
394 if (ReadDetection)
395 {
396 SetBit(Msr - 0xC0000000, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 1024));
397 }
398 if (WriteDetection)
399 {
400 SetBit(Msr - 0xC0000000, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 3072));
401 }
402 }
403 else
404 {
405 return FALSE;
406 }
407 return TRUE;
408}
VOID SetBit(INT BitNumber, ULONG *Addr)
set the bit
Definition Bitwise.c:46

◆ MsrHandleUnSetMsrBitmap()

BOOLEAN MsrHandleUnSetMsrBitmap ( VIRTUAL_MACHINE_STATE * VCpu,
UINT32 Msr,
BOOLEAN ReadDetection,
BOOLEAN WriteDetection )

UnSet bits in Msr Bitmap.

Parameters
VCpuThe virtual processor's state
MsrMSR Address
ReadDetectionUnset read bit
WriteDetectionUnset write bit
Returns
BOOLEAN Returns true if the MSR Bitmap is successfully applied or false if not applied
421{
422 if (!ReadDetection && !WriteDetection)
423 {
424 //
425 // Invalid Command
426 //
427 return FALSE;
428 }
429
430 if (Msr <= 0x00001FFF)
431 {
432 if (ReadDetection)
433 {
435 }
436 if (WriteDetection)
437 {
438 ClearBit(Msr, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
439 }
440 }
441 else if ((0xC0000000 <= Msr) && (Msr <= 0xC0001FFF))
442 {
443 if (ReadDetection)
444 {
445 ClearBit(Msr - 0xC0000000, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 1024));
446 }
447 if (WriteDetection)
448 {
449 ClearBit(Msr - 0xC0000000, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 3072));
450 }
451 }
452 else
453 {
454 return FALSE;
455 }
456 return TRUE;
457}

◆ MsrHandleWrmsrVmexit()

VOID MsrHandleWrmsrVmexit ( VIRTUAL_MACHINE_STATE * VCpu)

Handles in the cases when RDMSR causes a vm-exit.

Parameters
VCpuThe virtual processor's state
Returns
VOID
234{
235 UINT32 TargetMsr;
236 BOOLEAN UnusedIsKernel;
237 MSR Msr = {0};
238 PGUEST_REGS GuestRegs = VCpu->Regs;
239
240 //
241 // Execute WRMSR or RDMSR on behalf of the guest. Important that this
242 // can cause bug check when the guest tries to access unimplemented MSR
243 // even within the SEH block* because the below WRMSR or RDMSR raises
244 // #GP and are not protected by the SEH block (or cannot be protected
245 // either as this code run outside the thread stack region Windows
246 // requires to proceed SEH). Hypervisors typically handle this by noop-ing
247 // WRMSR and returning zero for RDMSR with non-architecturally defined
248 // MSRs. Alternatively, one can probe which MSRs should cause #GP prior
249 // to installation of a hypervisor and the hypervisor can emulate the
250 // results.
251 //
252 TargetMsr = GuestRegs->rcx & 0xffffffff;
253
254 Msr.Fields.Low = (ULONG)GuestRegs->rax;
255 Msr.Fields.High = (ULONG)GuestRegs->rdx;
256
257 // LogInfo("MSR write (WRMSR) VM-exit, MSR: %x, rax: %llx, rdx: %llx, from: %llx",
258 // TargetMsr,
259 // GuestRegs->rax,
260 // GuestRegs->rdx,
261 // VCpu->LastVmexitRip);
262
263 //
264 // Checking whether it is a synthetic MSR for Hyper-V
265 //
267 {
268 CpuWriteMsr(TargetMsr, Msr.Flags);
269 return;
270 }
271
272 //
273 // Check for sanity of MSR if they're valid or they're for reserved range for WRMSR and RDMSR
274 //
275 if ((TargetMsr <= 0x00001FFF) || ((0xC0000000 <= TargetMsr) && (TargetMsr <= 0xC0001FFF)) ||
276 (TargetMsr >= RESERVED_MSR_RANGE_LOW && (TargetMsr <= RESERVED_MSR_RANGE_HI)))
277 {
278 //
279 // If the source register contains a non-canonical address and ECX specifies
280 // one of the following MSRs:
281 //
282 // IA32_DS_AREA, IA32_FS_BASE, IA32_GS_BASE, IA32_KERNEL_GSBASE, IA32_LSTAR,
283 // IA32_SYSENTER_EIP, IA32_SYSENTER_ESP
284 //
285 switch (TargetMsr)
286 {
287 case IA32_DS_AREA:
288 case IA32_FS_BASE:
289 case IA32_GS_BASE:
290 case IA32_KERNEL_GS_BASE:
291 case IA32_LSTAR:
292 case IA32_SYSENTER_EIP:
293 case IA32_SYSENTER_ESP:
294
295 if (!CheckAddressCanonicality(Msr.Flags, &UnusedIsKernel))
296 {
297 //
298 // Address is not canonical, inject #GP
299 //
301
302 return;
303 }
304
305 break;
306 }
307
308 //
309 // Perform MSR change
310 //
311 switch (TargetMsr)
312 {
313 case IA32_SYSENTER_CS:
314 VmxVmwrite64(VMCS_GUEST_SYSENTER_CS, Msr.Flags);
315 break;
316
317 case IA32_SYSENTER_ESP:
318 VmxVmwrite64(VMCS_GUEST_SYSENTER_ESP, Msr.Flags);
319 break;
320
321 case IA32_SYSENTER_EIP:
322 VmxVmwrite64(VMCS_GUEST_SYSENTER_EIP, Msr.Flags);
323 break;
324
325 case IA32_GS_BASE:
326 VmxVmwrite64(VMCS_GUEST_GS_BASE, Msr.Flags);
327 break;
328
329 case IA32_FS_BASE:
330 VmxVmwrite64(VMCS_GUEST_FS_BASE, Msr.Flags);
331 break;
332
333 default:
334
335 //
336 // Check for the footprints of the WRMSR in the transparent mode
337 //
339 {
340 return;
341 }
342
343 //
344 // Perform the WRMSR
345 //
346 CpuWriteMsr((ULONG)GuestRegs->rcx, Msr.Flags);
347
348 break;
349 }
350 }
351 else
352 {
353 //
354 // Msr is invalid, inject #GP
355 //
357 return;
358 }
359}
BOOLEAN CheckAddressCanonicality(UINT64 VAddr, PBOOLEAN IsKernelAddress)
Checks if the address is canonical based on x86 processor's virtual address width or not.
Definition AddressCheck.c:66
VOID CpuWriteMsr(ULONG MsrAddress, UINT64 MsrValue)
Write an MSR.
Definition PlatformIntrinsics.c:233
UCHAR VmxVmwrite64(size_t Field, UINT64 FieldValue)
VMX VMWRITE instruction (64-bit).
Definition PlatformIntrinsicsVmx.c:273
UCHAR BOOLEAN
Definition BasicTypes.h:35
IMPORT_EXPORT_HYPEREVADE BOOLEAN TransparentCheckAndModifyMsrWrite(PGUEST_REGS Regs, UINT32 TargetMsr)
Handle WRMSR VM exits when the Transparent mode is enabled.
Definition VmxFootprints.c:107