Bitdefender Hypervisor Memory Introspection
kernvm.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "kernvm.h"
6 #include "hook.h"
7 #include "icache.h"
8 #include "introcpu.h"
9 
10 
13  _In_ QWORD VirtualAddress,
14  _Out_ DWORD *OffsetsCount,
16  )
30 {
31  DWORD count;
32 
33  if (NULL == OffsetsCount)
34  {
36  }
37 
38  if (NULL == OffsetsTrace)
39  {
41  }
42 
43  count = 0;
44 
45  if (gGuest.Guest64 && gGuest.LA57)
46  {
47  OffsetsTrace[count++] = 8ull * PML5_INDEX(VirtualAddress);
48  OffsetsTrace[count++] = 8ull * PML4_INDEX(VirtualAddress);
49  OffsetsTrace[count++] = 8ull * PDP_INDEX(VirtualAddress);
50  OffsetsTrace[count++] = 8ull * PD_INDEX(VirtualAddress);
51  OffsetsTrace[count++] = 8ull * PT_INDEX(VirtualAddress);
52  }
53  else if (gGuest.Guest64)
54  {
55  OffsetsTrace[count++] = 8ull * PML4_INDEX(VirtualAddress);
56  OffsetsTrace[count++] = 8ull * PDP_INDEX(VirtualAddress);
57  OffsetsTrace[count++] = 8ull * PD_INDEX(VirtualAddress);
58  OffsetsTrace[count++] = 8ull * PT_INDEX(VirtualAddress);
59  }
60  else
61  {
62  if (gGuest.PaeEnabled)
63  {
64  // PAE paging
65  OffsetsTrace[count++] = 8ull * (((DWORD)VirtualAddress & 0xC0000000) >> 30);
66  OffsetsTrace[count++] = 8ull * PD_INDEX(VirtualAddress);
67  OffsetsTrace[count++] = 8ull * PT_INDEX(VirtualAddress);
68  }
69  else
70  {
71  // Standard 32 bit paging
72  OffsetsTrace[count++] = 4ull * PD32_INDEX(VirtualAddress);
73  OffsetsTrace[count++] = 4ull * PT32_INDEX(VirtualAddress);
74  }
75  }
76 
77  *OffsetsCount = count;
78 
79  return INT_STATUS_SUCCESS;
80 }
81 
82 
83 static INTSTATUS
85  _In_ QWORD VirtualAddress,
86  _In_ QWORD Cr3,
87  _In_ QWORD CurrentPage,
88  _In_ BYTE PagingMode,
89  _In_ BYTE Level,
91  )
109 {
110  INTSTATUS status;
111  QWORD localVirtualAddress;
112  DWORD i;
113 
114  if (0 == CurrentPage)
115  {
117  }
118 
119  if (0 == Level)
120  {
122  }
123 
124  if (PAGING_5_LEVEL_MODE == PagingMode)
125  {
126  PQWORD pPage;
127 
128  status = IntPhysMemMap(CurrentPage, PAGE_SIZE, 0, &pPage);
129  if (!INT_SUCCESS(status))
130  {
131  return status;
132  }
133 
134  for (i = 0; i < PAGE_SIZE / 8; i++)
135  {
136  localVirtualAddress = PAGE_SX(VirtualAddress | ((QWORD)i << (12 + (9 * (Level - 1)))));
137 
138  if (pPage[i] & 1)
139  {
140  if (1 == Level)
141  {
142  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_4K);
143  }
144  else if ((2 == Level) && (0 != (pPage[i] & PD_PS)))
145  {
146  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_2M);
147  }
148  else if ((3 == Level) && (0 != (pPage[i] & PDP_PS)))
149  {
150  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_1G);
151  }
152  else if ((4 == Level) && (0 != (pPage[i] & PDP_PS)))
153  {
154  status = Callback(Cr3, localVirtualAddress, pPage[i], 512 * PAGE_SIZE_1G);
155  }
156  else
157  {
158  status = IntIterateVirtualAddressSpaceRec(localVirtualAddress,
159  Cr3,
160  pPage[i] & PHYS_PAGE_MASK,
161  PagingMode,
162  Level - 1,
163  Callback);
164  }
165  }
166  }
167 
168  IntPhysMemUnmap(&pPage);
169 
170  }
171  else if (PAGING_4_LEVEL_MODE == PagingMode)
172  {
173  PQWORD pPage;
174 
175  status = IntPhysMemMap(CurrentPage, PAGE_SIZE, 0, &pPage);
176  if (!INT_SUCCESS(status))
177  {
178  return status;
179  }
180 
181  for (i = 0; i < PAGE_SIZE / 8; i++)
182  {
183  localVirtualAddress = PAGE_SX(VirtualAddress | ((QWORD)i << (12 + (9 * (Level - 1)))));
184 
185  if (pPage[i] & 1)
186  {
187  if ((pPage[i] & PHYS_PAGE_MASK) == (CurrentPage & PHYS_PAGE_MASK))
188  {
189  // self-map, ignore.
190  continue;
191  }
192 
193  if (1 == Level)
194  {
195  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_4K);
196  }
197  else if ((2 == Level) && (0 != (pPage[i] & PD_PS)))
198  {
199  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_2M);
200  }
201  else if ((3 == Level) && (0 != (pPage[i] & PDP_PS)))
202  {
203  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_1G);
204  }
205  else
206  {
207  status = IntIterateVirtualAddressSpaceRec(localVirtualAddress,
208  Cr3,
209  pPage[i] & PHYS_PAGE_MASK,
210  PagingMode,
211  Level - 1,
212  Callback);
213  }
214  }
215  }
216 
217  IntPhysMemUnmap(&pPage);
218 
219  }
220  else if (PAGING_PAE_MODE == PagingMode)
221  {
222  PQWORD pPage;
223 
224  if (3 == Level)
225  {
226  status = IntPhysMemMap(CurrentPage, PAGE_SIZE, 0, &pPage);
227  }
228  else
229  {
230  status = IntPhysMemMap(CurrentPage, 32, 0, &pPage);
231  }
232  if (!INT_SUCCESS(status))
233  {
234  return status;
235  }
236 
237  for (i = 0; i < (DWORD)((3 == Level) ? 4 : (PAGE_SIZE / 8)); i++)
238  {
239  localVirtualAddress = ((DWORD)VirtualAddress | (i << (12 + (9 * (Level - 1)))));
240 
241  if ((pPage[i] & PHYS_PAGE_MASK) == (CurrentPage & PHYS_PAGE_MASK))
242  {
243  // self-map, ignore.
244  continue;
245  }
246 
247  if (pPage[i] & 1)
248  {
249  if (1 == Level)
250  {
251  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_4K);
252  }
253  else if ((2 == Level) && (0 != (pPage[i] & PD_PS)))
254  {
255  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_2M);
256  }
257  else
258  {
259  status = IntIterateVirtualAddressSpaceRec(localVirtualAddress,
260  Cr3,
261  pPage[i] & PHYS_PAGE_MASK,
262  PagingMode,
263  Level - 1,
264  Callback);
265  }
266  }
267  }
268 
269  IntPhysMemUnmap(&pPage);
270 
271  }
272  else if (PAGING_NORMAL_MODE == PagingMode)
273  {
274  PDWORD pPage;
275 
276  status = IntPhysMemMap(CurrentPage, PAGE_SIZE, 0, &pPage);
277  if (!INT_SUCCESS(status))
278  {
279  return status;
280  }
281 
282  for (i = 0; i < PAGE_SIZE / 4; i++)
283  {
284  localVirtualAddress = ((DWORD)VirtualAddress | (i << (12 + (10 * (Level - 1)))));
285 
286  if (pPage[i] & 1)
287  {
288  if (((QWORD)pPage[i] & PHYS_PAGE_MASK) == (CurrentPage & PHYS_PAGE_MASK))
289  {
290  // self-map, ignore.
291  continue;
292  }
293 
294  if (1 == Level)
295  {
296  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_4K);
297  }
298  else if ((2 == Level) && (0 != (pPage[i] & PD_PS)))
299  {
300  status = Callback(Cr3, localVirtualAddress, pPage[i], PAGE_SIZE_4M);
301  }
302  else
303  {
304  status = IntIterateVirtualAddressSpaceRec(localVirtualAddress,
305  Cr3,
306  pPage[i] & PHYS_PAGE_MASK,
307  PagingMode,
308  Level - 1,
309  Callback);
310  }
311  }
312  }
313 
314  IntPhysMemUnmap(&pPage);
315 
316  }
317  else
318  {
320  }
321 
322  return status;
323 }
324 
325 
326 INTSTATUS
328  _In_ QWORD Cr3,
330  )
344 {
345  INTSTATUS status;
346  QWORD efer, cr0, cr4;
347 
348  if ((0 == Cr3) || (0 != (Cr3 & PAGE_OFFSET)))
349  {
351  }
352 
353  if (NULL == Callback)
354  {
356  }
357 
358  efer = 0;
359  cr0 = 0;
360  cr4 = 0;
361 
362  status = IntCr0Read(IG_CURRENT_VCPU, &cr0);
363  if (!INT_SUCCESS(status))
364  {
365  return status;
366  }
367 
368  status = IntCr4Read(IG_CURRENT_VCPU, &cr4);
369  if (!INT_SUCCESS(status))
370  {
371  return status;
372  }
373 
374  status = IntEferRead(IG_CURRENT_VCPU, &efer);
375  if (!INT_SUCCESS(status))
376  {
377  return status;
378  }
379 
380  if (0 != (efer & EFER_LMA) && 0 != (cr4 & CR4_LA57))
381  {
382  status = IntIterateVirtualAddressSpaceRec(0, Cr3, Cr3, PAGING_5_LEVEL_MODE, 5, Callback);
383  }
384  else if (0 != (efer & EFER_LMA))
385  {
386  status = IntIterateVirtualAddressSpaceRec(0, Cr3, Cr3, PAGING_4_LEVEL_MODE, 4, Callback);
387  }
388  else if (0 != (cr4 & CR4_PAE))
389  {
390  status = IntIterateVirtualAddressSpaceRec(0, Cr3, Cr3, PAGING_PAE_MODE, 3, Callback);
391  }
392  else if (0 != (cr0 & CR0_PG))
393  {
394  status = IntIterateVirtualAddressSpaceRec(0, Cr3, Cr3, PAGING_NORMAL_MODE, 2, Callback);
395  }
396  else
397  {
398  status = INT_STATUS_NOT_SUPPORTED;
399  }
400 
401  return status;
402 }
403 
404 
405 INTSTATUS
407  _In_ QWORD Cr3,
408  _In_ QWORD VirtualAddress,
409  _In_ DWORD Size,
410  _In_ DWORD Ring
411  )
434 {
435  INTSTATUS status;
436  VA_TRANSLATION tr = {0};
437  QWORD va;
438  BYTE r, w, x;
439 
440  r = w = x = 0;
441 
442  for (va = VirtualAddress & PAGE_MASK; va < VirtualAddress + Size; va += PAGE_SIZE)
443  {
444  status = IntTranslateVirtualAddressEx(va, Cr3, TRFLG_NONE, &tr);
445  if (!INT_SUCCESS(status))
446  {
447  ERROR("[ERROR] IntTranslateVirtualAddressEx failed: 0x%08x\n", status);
448  return status;
449  }
450 
451  // Make sure the page is present.
452  if (0 == (tr.Flags & PT_P))
453  {
454  ERROR("[ERROR] Page %llx is not present!\n", va);
456  }
457 
458  // Make sure the page is writable.
459  if (!tr.IsWritable)
460  {
461  ERROR("[ERROR] Page %llx is not writable!\n", va);
463  }
464 
465  // Make sure rings match.
466  if ((0 == Ring) && tr.IsUser)
467  {
468  ERROR("[ERROR] Page %llx is not a kernel page!\n", va);
470  }
471 
472  if ((3 == Ring) && !tr.IsUser)
473  {
474  ERROR("[ERROR] Page %llx is not a user page!\n", va);
476  }
477 
478  // Make sure it is writable in EPT.
480  if (!INT_SUCCESS(status))
481  {
482  ERROR("[ERROR] IntHookGpaGetEPTPageProtection failed: 0x%08x\n", status);
483  return status;
484  }
485 
486  if (w == 0)
487  {
488  ERROR("[ERROR] Page %llx is not a writable in EPT!\n", va);
490  }
491  }
492 
493  return INT_STATUS_SUCCESS;
494 }
495 
496 
497 INTSTATUS
499  _In_ QWORD Cr3,
500  _In_ QWORD VirtualAddress,
501  _In_ DWORD Size,
502  _In_reads_bytes_(Size) void *Buffer,
503  _In_ DWORD Ring
504  )
522 {
523  INTSTATUS status;
524  VA_TRANSLATION tr = {0};
525  PBYTE *pa;
526  QWORD va;
527  DWORD pagesCount, i, left, offset;
528  BYTE r, w, x;
529  PBYTE pbuf;
530 
531  pa = NULL;
532  i = 0;
533  r = w = x = 0;
534  pbuf = NULL;
535 
536  // Handle potential overflows.
537  if (Size == 0)
538  {
540  }
541 
542  if (VirtualAddress + Size - 1 < VirtualAddress)
543  {
545  }
546 
547  pagesCount = Size / PAGE_SIZE + 2;
548 
549  pa = HpAllocWithTag(pagesCount * sizeof(void *), IC_TAG_ALLOC);
550  if (NULL == pa)
551  {
553  }
554 
555  // Before actually parsing & injecting our code/data inside the guest, we must invalidate the instruction cache.
556  // In some cases, Windows re-uses the INIT section of the kernel as non-paged memory. However, the original
557  // translations are not modified and the physical pages are not written, so there's no reason to invalidate
558  // those pages inside the cache. However, when we write guest memory, we may patch cached pages, which may lead
559  // to problems. In order to make things safe, we invalidate the cache.
560  if (NULL != gGuest.InstructionCache)
561  {
563  if (!INT_SUCCESS(status))
564  {
565  ERROR("[ERROR] IntIcFlush failed: 0x%08x\n", status);
566  }
567  }
568 
569  if (0 == Cr3)
570  {
571  status = IntCr3Read(IG_CURRENT_VCPU, &Cr3);
572  if (!INT_SUCCESS(status))
573  {
574  ERROR("[ERROR] IntCr3Read failed: 0x%08x\n", status);
575  goto cleanup_and_exit;
576  }
577  }
578 
579  for (va = VirtualAddress & PAGE_MASK; va <= VirtualAddress + Size - 1; va += PAGE_SIZE)
580  {
581  // Translate the given VA
582  status = IntTranslateVirtualAddressEx(va, Cr3, TRFLG_NONE, &tr);
583  if (!INT_SUCCESS(status))
584  {
585  ERROR("[ERROR] IntTranslateVirtualAddressEx failed: 0x%08x\n", status);
586  goto cleanup_and_exit;
587  }
588 
589  // Make sure the page is present.
590  if (0 == (tr.Flags & PT_P))
591  {
592  ERROR("[ERROR] Page %llx is not present!\n", va);
594  goto cleanup_and_exit;
595  }
596 
597  // Make sure the page is writable. No need to check CR0.WP, as we deny writes if the page is not writable.
598  if (!tr.IsWritable)
599  {
600  ERROR("[ERROR] Page %llx is not writable!\n", va);
601  status = INT_STATUS_ACCESS_DENIED;
602  goto cleanup_and_exit;
603  }
604 
605  // Make sure rings match. No need to check SMAP, since we write user pages only for ring3. No need to check
606  // SMEP either, as we're only concerned with writes.
607  if ((0 == Ring) && tr.IsUser)
608  {
609  ERROR("[ERROR] Page %llx is not a kernel page!\n", va);
610  status = INT_STATUS_ACCESS_DENIED;
611  goto cleanup_and_exit;
612  }
613 
614  if ((3 == Ring) && !tr.IsUser)
615  {
616  ERROR("[ERROR] Page %llx is not a user page!\n", va);
617  status = INT_STATUS_ACCESS_DENIED;
618  goto cleanup_and_exit;
619  }
620 
621  // Make sure it is writable in EPT.
623  if (!INT_SUCCESS(status))
624  {
625  ERROR("[ERROR] IntHookGpaGetEPTPageProtection failed: 0x%08x\n", status);
626  goto cleanup_and_exit;
627  }
628 
629  if (w == 0)
630  {
631  BYTE ir, iw, ix;
632 
633  ir = iw = ix = 1;
634 
635  status = IntHookGpaIsPageHooked(tr.PhysicalAddress, &ir, &iw, &ix);
636  if (!INT_SUCCESS(status))
637  {
638  ERROR("[ERROR] IntHookGpaIsPageHooked failed: 0x%08x\n", status);
639  goto cleanup_and_exit;
640  }
641 
642  if (iw == 0)
643  {
644  ERROR("[ERROR] Page %llx/%llx is not a writable in EPT!\n", va, tr.PhysicalAddress);
645  status = INT_STATUS_ACCESS_DENIED;
646  goto cleanup_and_exit;
647  }
648  }
649 
650  status = IntPhysMemMap(tr.PhysicalAddress, PAGE_SIZE, 0, &pa[i++]);
651  if (!INT_SUCCESS(status))
652  {
653  ERROR("[ERROR] IntPhysMemMap failed: 0x%08x\n", status);
654  goto cleanup_and_exit;
655  }
656  }
657 
658  // Do the actual writes inside the mapped pages.
659  pbuf = (PBYTE)Buffer;
660  left = Size;
661  va = VirtualAddress;
662  offset = 0;
663  i = 0;
664 
665  pa[0] += VirtualAddress & 0xFFF;
666 
667  while (left > 0)
668  {
669  DWORD currentSize = MIN(left, PAGE_REMAINING(va));
670 
671  memcpy(pa[i++], pbuf + offset, currentSize);
672 
673  left -= currentSize;
674 
675  va += currentSize;
676 
677  offset += currentSize;
678  }
679 
680  pa[0] -= VirtualAddress & 0xFFF;
681 
682  status = INT_STATUS_SUCCESS;
683 
684 cleanup_and_exit:
685  if (NULL != pa)
686  {
687  for (i = 0; i < pagesCount; i++)
688  {
689  if (NULL != pa[i])
690  {
691  IntPhysMemUnmap(&pa[i]);
692  }
693  }
694 
696  }
697 
698  return status;
699 }
#define INT_STATUS_ACCESS_DENIED
Definition: introstatus.h:290
#define INT_STATUS_PAGE_NOT_PRESENT
Indicates that a virtual address is not present.
Definition: introstatus.h:438
QWORD PhysicalAddress
The physical address to which VirtualAddress translates to.
Definition: introcore.h:107
#define _Out_
Definition: intro_sal.h:22
uint8_t BYTE
Definition: intro_types.h:47
#define CR0_PG
Definition: processor.h:40
#define _In_
Definition: intro_sal.h:21
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
INTSTATUS IntIterateVirtualAddressSpace(QWORD Cr3, PFUNC_VirtualAddressSpaceCallback Callback)
Iterate an entire virtual address space.
Definition: kernvm.c:327
#define PAGE_REMAINING(addr)
Definition: pgtable.h:163
BOOLEAN IsWritable
True if this page is writable.
Definition: introcore.h:132
static INTSTATUS IntIterateVirtualAddressSpaceRec(QWORD VirtualAddress, QWORD Cr3, QWORD CurrentPage, BYTE PagingMode, BYTE Level, PFUNC_VirtualAddressSpaceCallback Callback)
Iterate, recursively, an entire virtual address space.
Definition: kernvm.c:84
INTSTATUS(* PFUNC_VirtualAddressSpaceCallback)(QWORD Cr3, QWORD VirtualAddress, QWORD Entry, QWORD PageSize)
The type of callback invoked by PFUNC_IntIterateVaSpace while iterating the guest virtual address spa...
Definition: glueiface.h:1814
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
INTSTATUS IntHookGpaIsPageHooked(QWORD Gpa, BYTE *Read, BYTE *Write, BYTE *Execute)
Get the read, write and execute access for the given guest physical page.
Definition: hook_gpa.c:1006
INTSTATUS IntHookGpaGetEPTPageProtection(DWORD EptIndex, QWORD Address, BYTE *Read, BYTE *Write, BYTE *Execute)
Get the EPT page protection for the indicated guest physical address.
Definition: hook_gpa.c:1454
#define PD_INDEX(a)
Definition: pgtable.h:97
#define PT32_INDEX(a)
Definition: pgtable.h:108
#define PAGE_OFFSET
Definition: pgtable.h:32
#define ERROR(fmt,...)
Definition: glue.h:62
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
#define PHYS_PAGE_MASK
Definition: pgtable.h:38
int INTSTATUS
The status data type.
Definition: introstatus.h:24
#define TRFLG_NONE
No special options.
Definition: introcore.h:82
#define _Out_writes_(expr)
Definition: intro_sal.h:28
#define MIN(a, b)
Definition: introdefs.h:146
#define PML4_INDEX(a)
Definition: pgtable.h:95
#define PAGE_SX(addr)
Definition: pgtable.h:147
uint32_t * PDWORD
Definition: intro_types.h:49
#define PAGE_SIZE_4M
Definition: pgtable.h:20
INTSTATUS IntValidateRangeForWrite(QWORD Cr3, QWORD VirtualAddress, DWORD Size, DWORD Ring)
Validate a range of virtual memory for write.
Definition: kernvm.c:406
#define CR4_LA57
Definition: processor.h:55
5-level paging
Definition: introcore.h:72
QWORD Flags
The entry that maps VirtualAddress to PhysicalAddress, together with all the control bits...
Definition: introcore.h:119
#define PDP_INDEX(a)
Definition: pgtable.h:96
#define CR4_PAE
Definition: processor.h:48
#define IG_CURRENT_VCPU
For APIs that take a VCPU number as a parameter, this can be used to specify that the current VCPU sh...
Definition: glueiface.h:324
uint8_t * PBYTE
Definition: intro_types.h:47
BOOLEAN PaeEnabled
True if Physical Address Extension is enabled.
Definition: guests.h:295
#define PT_P
Definition: pgtable.h:83
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:290
unsigned long long QWORD
Definition: intro_types.h:53
INTSTATUS IntCr0Read(DWORD CpuNumber, QWORD *Cr0Value)
Reads the value of the guest CR0.
Definition: introcpu.c:363
#define INT_STATUS_INVALID_PARAMETER_4
Definition: introstatus.h:71
INTSTATUS IntSplitVirtualAddress(QWORD VirtualAddress, DWORD *OffsetsCount, QWORD *OffsetsTrace)
Split a linear address into page-table indexes.
Definition: kernvm.c:12
#define HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
#define PML5_INDEX(a)
Definition: pgtable.h:94
#define INT_STATUS_INVALID_PARAMETER_5
Definition: introstatus.h:74
INTSTATUS IntTranslateVirtualAddressEx(QWORD Gva, QWORD Cr3, DWORD Flags, VA_TRANSLATION *Translation)
Translates a guest virtual address to a guest physical address.
Definition: introcore.c:1863
32-bit paging with PAE
Definition: introcore.h:70
4-level paging
Definition: introcore.h:71
#define PAGE_SIZE
Definition: common.h:70
void * InstructionCache
The currently used instructions cache.
Definition: guests.h:404
#define PT_INDEX(a)
Definition: pgtable.h:98
uint32_t DWORD
Definition: intro_types.h:49
INTSTATUS IntVirtMemSafeWrite(QWORD Cr3, QWORD VirtualAddress, DWORD Size, void *Buffer, DWORD Ring)
Safely modify guest memory.
Definition: kernvm.c:498
#define _In_reads_bytes_(expr)
Definition: intro_sal.h:25
#define PAGE_SIZE_2M
Definition: pgtable.h:15
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
#define IC_TAG_ALLOC
Memory allocation.
Definition: memtags.h:28
#define EFER_LMA
Definition: processor.h:94
#define PAGE_SIZE_1G
Definition: pgtable.h:25
INTSTATUS IntIcFlush(PINS_CACHE Cache)
Flush the entire instruction cache.
Definition: icache.c:537
BOOLEAN LA57
True if 5-level paging is being used.
Definition: guests.h:296
#define PD32_INDEX(a)
Definition: pgtable.h:107
INTSTATUS IntCr3Read(DWORD CpuNumber, QWORD *Cr3Value)
Reads the value of the guest CR3.
Definition: introcpu.c:415
INTSTATUS IntCr4Read(DWORD CpuNumber, QWORD *Cr4Value)
Reads the value of the guest CR4.
Definition: introcpu.c:467
__must_check INTSTATUS IntPhysMemMap(QWORD PhysAddress, DWORD Length, DWORD Flags, void **HostPtr)
Maps a guest physical address inside Introcore VA space.
Definition: glue.c:338
#define PD_PS
Definition: pgtable.h:78
Encapsulates information about a virtual to physical memory translation.
Definition: introcore.h:102
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
#define INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
32-bit paging
Definition: introcore.h:69
#define PDP_PS
Definition: pgtable.h:67
unsigned long long * PQWORD
Definition: intro_types.h:53
INTSTATUS IntPhysMemUnmap(void **HostPtr)
Unmaps an address previously mapped with IntPhysMemMap.
Definition: glue.c:396
#define PAGE_MASK
Definition: pgtable.h:35
#define PAGE_SIZE_4K
Definition: pgtable.h:10
BOOLEAN IsUser
True if this page is accessible to user mode code.
Definition: introcore.h:128
DWORD UntrustedEptIndex
The EPTP index of the untrusted EPT.
Definition: guests.h:397
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
INTSTATUS IntEferRead(QWORD CpuNumber, QWORD *Efer)
Reads the value of the guest IA32 EFER MSR.
Definition: introcpu.c:12
#define MAX_TRANSLATION_DEPTH
Maximum depth of the translation hierarchy.
Definition: introcore.h:61
#define INT_STATUS_INSUFFICIENT_RESOURCES
Definition: introstatus.h:281
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68